1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include <sys/socket.h>
24 #include <sys/types.h>
35 #include "socket-util.h"
36 #include "sd-daemon.h"
38 #include "bus-internal.h"
39 #include "bus-message.h"
44 const char *arg_address = "kernel:path=/dev/kdbus/0-system/bus;unix:path=/run/dbus/system_bus_socket";
46 const char *arg_address = "unix:path=/run/dbus/system_bus_socket";
49 static int help(void) {
51 printf("%s [OPTIONS...]\n\n"
52 "Connect STDIO or a socket to a given bus address.\n\n"
53 " -h --help Show this help\n"
54 " --version Show package version\n"
55 " --address=ADDRESS Connect to bus specified by address\n",
56 program_invocation_short_name);
61 static int parse_argv(int argc, char *argv[]) {
68 static const struct option options[] = {
69 { "help", no_argument, NULL, 'h' },
70 { "version", no_argument, NULL, ARG_VERSION },
71 { "address", required_argument, NULL, ARG_ADDRESS },
80 while ((c = getopt_long(argc, argv, "hsup:", options, NULL)) >= 0) {
90 puts(SYSTEMD_FEATURES);
101 assert_not_reached("Unhandled option");
108 int main(int argc, char *argv[]) {
109 _cleanup_bus_unref_ sd_bus *a = NULL, *b = NULL;
110 sd_id128_t server_id;
112 int r, in_fd, out_fd;
114 log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
115 log_parse_environment();
118 r = parse_argv(argc, argv);
122 r = sd_listen_fds(0);
124 in_fd = STDIN_FILENO;
125 out_fd = STDOUT_FILENO;
127 in_fd = SD_LISTEN_FDS_START;
128 out_fd = SD_LISTEN_FDS_START;
130 log_error("Illegal number of file descriptors passed\n");
135 sd_is_socket(in_fd, AF_UNIX, 0, 0) > 0 &&
136 sd_is_socket(out_fd, AF_UNIX, 0, 0) > 0;
140 log_error("Failed to allocate bus: %s", strerror(-r));
144 r = sd_bus_set_address(a, arg_address);
146 log_error("Failed to set address to connect to: %s", strerror(-r));
150 r = sd_bus_negotiate_fds(a, is_unix);
152 log_error("Failed to set FD negotiation: %s", strerror(-r));
158 log_error("Failed to start bus client: %s", strerror(-r));
162 r = sd_bus_get_server_id(a, &server_id);
164 log_error("Failed to get server ID: %s", strerror(-r));
170 log_error("Failed to allocate bus: %s", strerror(-r));
174 r = sd_bus_set_fd(b, in_fd, out_fd);
176 log_error("Failed to set fds: %s", strerror(-r));
180 r = sd_bus_set_server(b, 1, server_id);
182 log_error("Failed to set server mode: %s", strerror(-r));
186 r = sd_bus_negotiate_fds(b, is_unix);
188 log_error("Failed to set FD negotiation: %s", strerror(-r));
192 r = sd_bus_set_anonymous(b, true);
194 log_error("Failed to set anonymous authentication: %s", strerror(-r));
200 log_error("Failed to start bus client: %s", strerror(-r));
205 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
206 int events_a, events_b, fd;
207 uint64_t timeout_a, timeout_b, t;
208 struct timespec _ts, *ts;
210 r = sd_bus_process(a, &m);
212 log_error("Failed to process bus a: %s", strerror(-r));
217 r = sd_bus_send(b, m, NULL);
219 log_error("Failed to send message: %s", strerror(-r));
227 r = sd_bus_process(b, &m);
229 /* treat 'connection reset by peer' as clean exit condition */
230 if (r == -ECONNRESET)
237 r = sd_bus_send(a, m, NULL);
239 log_error("Failed to send message: %s", strerror(-r));
247 fd = sd_bus_get_fd(a);
249 log_error("Failed to get fd: %s", strerror(-r));
253 events_a = sd_bus_get_events(a);
255 log_error("Failed to get events mask: %s", strerror(-r));
259 r = sd_bus_get_timeout(a, &timeout_a);
261 log_error("Failed to get timeout: %s", strerror(-r));
265 events_b = sd_bus_get_events(b);
267 log_error("Failed to get events mask: %s", strerror(-r));
271 r = sd_bus_get_timeout(b, &timeout_b);
273 log_error("Failed to get timeout: %s", strerror(-r));
278 if (t == (uint64_t) -1 || (timeout_b != (uint64_t) -1 && timeout_b < timeout_a))
281 if (t == (uint64_t) -1)
286 nw = now(CLOCK_MONOTONIC);
292 ts = timespec_store(&_ts, t);
296 struct pollfd p[3] = {
297 {.fd = fd, .events = events_a, },
298 {.fd = STDIN_FILENO, .events = events_b & POLLIN, },
299 {.fd = STDOUT_FILENO, .events = events_b & POLLOUT, }};
301 r = ppoll(p, ELEMENTSOF(p), ts, NULL);
304 log_error("ppoll() failed: %m");
312 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;