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

Zbigniew Jędrzejewski-Szmek zbyszek at in.waw.pl
Mon Nov 18 19:00:38 PST 2013


On Fri, Nov 15, 2013 at 07:32:23PM +0100, Daniel Mack wrote:
> 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);
This will give bogus information if --bus-path xxx --help is used.

> +
> +        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;
> +        }
We usually use if() cases for those things. And indeed, a switch
here won't work, because r > 1 must be treated as an error condtion
too.

> +
>          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;
>                          }
>                  }

Zbyszek


More information about the systemd-devel mailing list