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"
43 #define DEFAULT_BUS_PATH "unix:path=/run/dbus/system_bus_socket"
45 const char *arg_bus_path = DEFAULT_BUS_PATH;
47 static int help(void) {
49 printf("%s [OPTIONS...]\n\n"
50 "STDIO or socket-activatable proxy to a given DBus endpoint.\n\n"
51 " -h --help Show this help\n"
52 " --version Show package version\n"
53 " -p --bus-path=PATH Path to the kernel bus (default: %s)\n",
54 program_invocation_short_name, DEFAULT_BUS_PATH);
59 static int parse_argv(int argc, char *argv[]) {
65 static const struct option options[] = {
66 { "help", no_argument, NULL, 'h' },
67 { "bus-path", required_argument, NULL, 'p' },
76 while ((c = getopt_long(argc, argv, "hsup:", options, NULL)) >= 0) {
86 puts(SYSTEMD_FEATURES);
93 arg_bus_path = optarg;
97 log_error("Unknown option code %c", c);
105 int main(int argc, char *argv[]) {
106 _cleanup_bus_unref_ sd_bus *a = NULL, *b = NULL;
107 sd_id128_t server_id;
109 int r, in_fd, out_fd;
111 log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
112 log_parse_environment();
115 r = parse_argv(argc, argv);
119 r = sd_listen_fds(0);
121 in_fd = STDIN_FILENO;
122 out_fd = STDOUT_FILENO;
124 in_fd = SD_LISTEN_FDS_START;
125 out_fd = SD_LISTEN_FDS_START;
127 log_error("Illegal number of file descriptors passed\n");
132 sd_is_socket(in_fd, AF_UNIX, 0, 0) > 0 &&
133 sd_is_socket(out_fd, AF_UNIX, 0, 0) > 0;
137 log_error("Failed to allocate bus: %s", strerror(-r));
141 r = sd_bus_set_address(a, arg_bus_path);
143 log_error("Failed to set address to connect to: %s", strerror(-r));
147 r = sd_bus_negotiate_fds(a, is_unix);
149 log_error("Failed to set FD negotiation: %s", strerror(-r));
155 log_error("Failed to start bus client: %s", strerror(-r));
159 r = sd_bus_get_server_id(a, &server_id);
161 log_error("Failed to get server ID: %s", strerror(-r));
167 log_error("Failed to allocate bus: %s", strerror(-r));
171 r = sd_bus_set_fd(b, in_fd, out_fd);
173 log_error("Failed to set fds: %s", strerror(-r));
177 r = sd_bus_set_server(b, 1, server_id);
179 log_error("Failed to set server mode: %s", strerror(-r));
183 r = sd_bus_negotiate_fds(b, is_unix);
185 log_error("Failed to set FD negotiation: %s", strerror(-r));
189 r = sd_bus_set_anonymous(b, true);
191 log_error("Failed to set anonymous authentication: %s", strerror(-r));
197 log_error("Failed to start bus client: %s", strerror(-r));
202 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
203 int events_a, events_b, fd;
204 uint64_t timeout_a, timeout_b, t;
205 struct timespec _ts, *ts;
207 r = sd_bus_process(a, &m);
209 log_error("Failed to process bus a: %s", strerror(-r));
214 r = sd_bus_send(b, m, NULL);
216 log_error("Failed to send message: %s", strerror(-r));
224 r = sd_bus_process(b, &m);
226 /* treat 'connection reset by peer' as clean exit condition */
227 if (r == -ECONNRESET)
234 r = sd_bus_send(a, m, NULL);
236 log_error("Failed to send message: %s", strerror(-r));
244 fd = sd_bus_get_fd(a);
246 log_error("Failed to get fd: %s", strerror(-r));
250 events_a = sd_bus_get_events(a);
252 log_error("Failed to get events mask: %s", strerror(-r));
256 r = sd_bus_get_timeout(a, &timeout_a);
258 log_error("Failed to get timeout: %s", strerror(-r));
262 events_b = sd_bus_get_events(b);
264 log_error("Failed to get events mask: %s", strerror(-r));
268 r = sd_bus_get_timeout(b, &timeout_b);
270 log_error("Failed to get timeout: %s", strerror(-r));
275 if (t == (uint64_t) -1 || (timeout_b != (uint64_t) -1 && timeout_b < timeout_a))
278 if (t == (uint64_t) -1)
283 nw = now(CLOCK_MONOTONIC);
289 ts = timespec_store(&_ts, t);
293 struct pollfd p[3] = {
294 {.fd = fd, .events = events_a, },
295 {.fd = STDIN_FILENO, .events = events_b & POLLIN, },
296 {.fd = STDOUT_FILENO, .events = events_b & POLLOUT, }};
298 r = ppoll(p, ELEMENTSOF(p), ts, NULL);
301 log_error("ppoll() failed: %m");
309 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;