]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/stdio-bridge/stdio-bridge.c
Use initalization instead of explicit zeroing
[thirdparty/systemd.git] / src / stdio-bridge / stdio-bridge.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2010 Lennart Poettering
7
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.
12
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.
17
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/>.
20 ***/
21
22 #include <sys/socket.h>
23 #include <sys/un.h>
24 #include <sys/types.h>
25 #include <fcntl.h>
26 #include <unistd.h>
27 #include <string.h>
28 #include <errno.h>
29 #include <sys/poll.h>
30 #include <stddef.h>
31
32 #include "log.h"
33 #include "util.h"
34 #include "socket-util.h"
35 #include "sd-daemon.h"
36 #include "sd-bus.h"
37 #include "bus-internal.h"
38 #include "bus-message.h"
39
40 int main(int argc, char *argv[]) {
41 _cleanup_bus_unref_ sd_bus *a = NULL, *b = NULL;
42 sd_id128_t server_id;
43 bool is_unix;
44 int r;
45
46 if (argc > 1) {
47 log_error("This program takes no argument.");
48 return EXIT_FAILURE;
49 }
50
51 log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
52 log_parse_environment();
53 log_open();
54
55 is_unix =
56 sd_is_socket(STDIN_FILENO, AF_UNIX, 0, 0) > 0 &&
57 sd_is_socket(STDOUT_FILENO, AF_UNIX, 0, 0) > 0;
58
59 r = sd_bus_new(&a);
60 if (r < 0) {
61 log_error("Failed to allocate bus: %s", strerror(-r));
62 goto finish;
63 }
64
65 r = sd_bus_set_address(a, "unix:path=/run/dbus/system_bus_socket");
66 if (r < 0) {
67 log_error("Failed to set address to connect to: %s", strerror(-r));
68 goto finish;
69 }
70
71 r = sd_bus_set_negotiate_fds(a, is_unix);
72 if (r < 0) {
73 log_error("Failed to set FD negotiation: %s", strerror(-r));
74 goto finish;
75 }
76
77 r = sd_bus_start(a);
78 if (r < 0) {
79 log_error("Failed to start bus client: %s", strerror(-r));
80 goto finish;
81 }
82
83 r = sd_bus_get_server_id(a, &server_id);
84 if (r < 0) {
85 log_error("Failed to get server ID: %s", strerror(-r));
86 goto finish;
87 }
88
89 r = sd_bus_new(&b);
90 if (r < 0) {
91 log_error("Failed to allocate bus: %s", strerror(-r));
92 goto finish;
93 }
94
95 r = sd_bus_set_fd(b, STDIN_FILENO, STDOUT_FILENO);
96 if (r < 0) {
97 log_error("Failed to set fds: %s", strerror(-r));
98 goto finish;
99 }
100
101 r = sd_bus_set_server(b, 1, server_id);
102 if (r < 0) {
103 log_error("Failed to set server mode: %s", strerror(-r));
104 goto finish;
105 }
106
107 r = sd_bus_set_negotiate_fds(b, is_unix);
108 if (r < 0) {
109 log_error("Failed to set FD negotiation: %s", strerror(-r));
110 goto finish;
111 }
112
113 r = sd_bus_set_anonymous(b, true);
114 if (r < 0) {
115 log_error("Failed to set anonymous authentication: %s", strerror(-r));
116 goto finish;
117 }
118
119 r = sd_bus_start(b);
120 if (r < 0) {
121 log_error("Failed to start bus client: %s", strerror(-r));
122 goto finish;
123 }
124
125 for (;;) {
126 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
127 int events_a, events_b, fd;
128 uint64_t timeout_a, timeout_b, t;
129 struct timespec _ts, *ts;
130
131 r = sd_bus_process(a, &m);
132 if (r < 0) {
133 log_error("Failed to process bus: %s", strerror(-r));
134 goto finish;
135 }
136
137 if (m) {
138 r = sd_bus_send(b, m, NULL);
139 if (r < 0) {
140 log_error("Failed to send message: %s", strerror(-r));
141 goto finish;
142 }
143 }
144
145 if (r > 0)
146 continue;
147
148 r = sd_bus_process(b, &m);
149 if (r < 0) {
150 log_error("Failed to process bus: %s", strerror(-r));
151 goto finish;
152 }
153
154 if (m) {
155 r = sd_bus_send(a, m, NULL);
156 if (r < 0) {
157 log_error("Failed to send message: %s", strerror(-r));
158 goto finish;
159 }
160 }
161
162 if (r > 0)
163 continue;
164
165 fd = sd_bus_get_fd(a);
166 if (fd < 0) {
167 log_error("Failed to get fd: %s", strerror(-r));
168 goto finish;
169 }
170
171 events_a = sd_bus_get_events(a);
172 if (events_a < 0) {
173 log_error("Failed to get events mask: %s", strerror(-r));
174 goto finish;
175 }
176
177 r = sd_bus_get_timeout(a, &timeout_a);
178 if (r < 0) {
179 log_error("Failed to get timeout: %s", strerror(-r));
180 goto finish;
181 }
182
183 events_b = sd_bus_get_events(b);
184 if (events_b < 0) {
185 log_error("Failed to get events mask: %s", strerror(-r));
186 goto finish;
187 }
188
189 r = sd_bus_get_timeout(b, &timeout_b);
190 if (r < 0) {
191 log_error("Failed to get timeout: %s", strerror(-r));
192 goto finish;
193 }
194
195 t = timeout_a;
196 if (t == (uint64_t) -1 || (timeout_b != (uint64_t) -1 && timeout_b < timeout_a))
197 t = timeout_b;
198
199 if (t == (uint64_t) -1)
200 ts = NULL;
201 else {
202 usec_t nw;
203
204 nw = now(CLOCK_MONOTONIC);
205 if (t > nw)
206 t -= nw;
207 else
208 t = 0;
209
210 ts = timespec_store(&_ts, t);
211 }
212
213 {
214 struct pollfd p[3] = {
215 {.fd = fd, .events = events_a, },
216 {.fd = STDIN_FILENO, .events = events_b & POLLIN, },
217 {.fd = STDOUT_FILENO, .events = events_b & POLLOUT, }};
218
219 r = ppoll(p, ELEMENTSOF(p), ts, NULL);
220 }
221 if (r < 0) {
222 log_error("ppoll() failed: %m");
223 goto finish;
224 }
225 }
226
227 r = 0;
228
229 finish:
230 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
231 }