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 _______________________________________________ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel