[systemd-devel] [PATCH 7/7] systemd-stdio-bridge: make it socket-activatable and usable as kdbus bridge

Daniel Mack zonque at gmail.com
Fri Nov 15 10:32:23 PST 2013


Augment systemd-stdio-bridge a bit to make it a 1:1 bridge from legacy
DBus clients to kdbus. In particular,

 * allow setting the bus path of the upstream bus as command line
   argument
 * use sd_listen_fds() for systemd's socket activation
 * omit calling sd_bus_negotiate_fds() when upstream bus is kdbus
 * reply to bus send errors with proper dbus error messages
 * treat -ECONNRESET as expected end-of-connection condition
---
 src/stdio-bridge/stdio-bridge.c | 116 +++++++++++++++++++++++++++++++++-------
 1 file changed, 98 insertions(+), 18 deletions(-)

diff --git a/src/stdio-bridge/stdio-bridge.c b/src/stdio-bridge/stdio-bridge.c
index 07218e9..f16a146 100644
--- a/src/stdio-bridge/stdio-bridge.c
+++ b/src/stdio-bridge/stdio-bridge.c
@@ -28,6 +28,7 @@
 #include <errno.h>
 #include <sys/poll.h>
 #include <stddef.h>
+#include <getopt.h>
 
 #include "log.h"
 #include "util.h"
@@ -37,25 +38,99 @@
 #include "bus-internal.h"
 #include "bus-message.h"
 #include "bus-util.h"
+#include "build.h"
+
+const char *arg_bus_path = "unix:path=/run/dbus/system_bus_socket";
+
+static int help(void) {
+
+        printf("%s [OPTIONS...]\n\n"
+               "Query or change system hostname.\n\n"
+               "  -h --help              Show this help\n"
+               "     --version           Show package version\n"
+               "     --bus-path          Path to the kernel bus (default: %s)\n",
+               program_invocation_short_name, arg_bus_path);
+
+        return 0;
+}
+
+static int parse_argv(int argc, char *argv[]) {
+
+        enum {
+                ARG_VERSION = 0x100,
+        };
+
+        static const struct option options[] = {
+                { "help",            no_argument,       NULL, 'h'     },
+                { "bus-path",        required_argument, NULL, 'p'     },
+                { NULL,              0,                 NULL, 0       }
+        };
+
+        int c;
+
+        assert(argc >= 0);
+        assert(argv);
+
+        while ((c = getopt_long(argc, argv, "hsup:", options, NULL)) >= 0) {
+
+                switch (c) {
+
+                case 'h':
+                        help();
+                        return 0;
+
+                case ARG_VERSION:
+                        puts(PACKAGE_STRING);
+                        puts(SYSTEMD_FEATURES);
+                        return 0;
+
+                case '?':
+                        return -EINVAL;
+
+                case 'p':
+                        arg_bus_path = optarg;
+                        break;
+
+                default:
+                        log_error("Unknown option code %c", c);
+                        return -EINVAL;
+                }
+        }
+
+        return 1;
+}
 
 int main(int argc, char *argv[]) {
         _cleanup_bus_unref_ sd_bus *a = NULL, *b = NULL;
         sd_id128_t server_id;
         bool is_unix;
-        int r;
-
-        if (argc > 1) {
-                log_error("This program takes no argument.");
-                return EXIT_FAILURE;
-        }
+        int r, in_fd, out_fd;
 
         log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
         log_parse_environment();
         log_open();
 
+        r = parse_argv(argc, argv);
+        if (r <= 0)
+                goto finish;
+
+        r = sd_listen_fds(0);
+        switch (r) {
+        case 0:
+                in_fd = STDIN_FILENO;
+                out_fd = STDOUT_FILENO;
+                break;
+        case 1:
+                in_fd = SD_LISTEN_FDS_START;
+                out_fd = SD_LISTEN_FDS_START;
+                break;
+        default:
+                goto finish;
+        }
+
         is_unix =
-                sd_is_socket(STDIN_FILENO, AF_UNIX, 0, 0) > 0 &&
-                sd_is_socket(STDOUT_FILENO, AF_UNIX, 0, 0) > 0;
+                sd_is_socket(in_fd, AF_UNIX, 0, 0) > 0 &&
+                sd_is_socket(out_fd, AF_UNIX, 0, 0) > 0;
 
         r = sd_bus_new(&a);
         if (r < 0) {
@@ -63,16 +138,18 @@ int main(int argc, char *argv[]) {
                 goto finish;
         }
 
-        r = sd_bus_set_address(a, "unix:path=/run/dbus/system_bus_socket");
+        r = sd_bus_set_address(a, arg_bus_path);
         if (r < 0) {
                 log_error("Failed to set address to connect to: %s", strerror(-r));
                 goto finish;
         }
 
-        r = sd_bus_negotiate_fds(a, is_unix);
-        if (r < 0) {
-                log_error("Failed to set FD negotiation: %s", strerror(-r));
-                goto finish;
+        if (!startswith(arg_bus_path, "kernel:")) {
+                r = sd_bus_negotiate_fds(a, is_unix);
+                if (r < 0) {
+                        log_error("Failed to set FD negotiation: %s", strerror(-r));
+                        goto finish;
+                }
         }
 
         r = sd_bus_start(a);
@@ -93,7 +170,7 @@ int main(int argc, char *argv[]) {
                 goto finish;
         }
 
-        r = sd_bus_set_fd(b, STDIN_FILENO, STDOUT_FILENO);
+        r = sd_bus_set_fd(b, in_fd, out_fd);
         if (r < 0) {
                 log_error("Failed to set fds: %s", strerror(-r));
                 goto finish;
@@ -131,14 +208,14 @@ int main(int argc, char *argv[]) {
 
                 r = sd_bus_process(a, &m);
                 if (r < 0) {
-                        log_error("Failed to process bus: %s", strerror(-r));
+                        log_error("Failed to process bus a: %s", strerror(-r));
                         goto finish;
                 }
 
                 if (m) {
                         r = sd_bus_send(b, m, NULL);
                         if (r < 0) {
-                                log_error("Failed to send message: %s", strerror(-r));
+                                sd_bus_reply_method_errno(a, m, r, NULL);
                                 goto finish;
                         }
                 }
@@ -148,14 +225,17 @@ int main(int argc, char *argv[]) {
 
                 r = sd_bus_process(b, &m);
                 if (r < 0) {
-                        log_error("Failed to process bus: %s", strerror(-r));
+                        /* treat 'connection reset by peer' as clean exit condition */
+                        if (r == -ECONNRESET)
+                                r = 0;
+
                         goto finish;
                 }
 
                 if (m) {
                         r = sd_bus_send(a, m, NULL);
                         if (r < 0) {
-                                log_error("Failed to send message: %s", strerror(-r));
+                                sd_bus_reply_method_errno(b, m, r, NULL);
                                 goto finish;
                         }
                 }
-- 
1.8.4.2



More information about the systemd-devel mailing list