[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