]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd-bus/busctl.c
Remove some unused variables
[thirdparty/systemd.git] / src / libsystemd-bus / busctl.c
CommitLineData
de1c301e
LP
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2013 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
1f849790
LP
22#include <getopt.h>
23
89ffcd2a
LP
24#include "strv.h"
25#include "util.h"
26#include "log.h"
1f849790
LP
27#include "build.h"
28#include "pager.h"
89ffcd2a 29
de1c301e 30#include "sd-bus.h"
89ffcd2a
LP
31#include "bus-message.h"
32#include "bus-internal.h"
40ca29a1 33#include "bus-util.h"
2b5c5383 34#include "bus-dump.h"
de1c301e 35
1f849790
LP
36static bool arg_no_pager = false;
37static char *arg_address = NULL;
1f849790
LP
38static bool arg_no_unique = false;
39static char **arg_matches = NULL;
d75edbd6
LP
40static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
41static char *arg_host = NULL;
42static bool arg_user = false;
1f849790
LP
43
44static void pager_open_if_enabled(void) {
45
46 /* Cache result before we open the pager */
47 if (arg_no_pager)
48 return;
49
50 pager_open(false);
51}
52
53static int list_bus_names(sd_bus *bus, char **argv) {
de1c301e
LP
54 _cleanup_strv_free_ char **l = NULL;
55 char **i;
56 int r;
89ffcd2a 57 size_t max_i = 0;
de1c301e 58
1f849790 59 assert(bus);
de1c301e
LP
60
61 r = sd_bus_list_names(bus, &l);
62 if (r < 0) {
63 log_error("Failed to list names: %s", strerror(-r));
1f849790 64 return r;
de1c301e
LP
65 }
66
1f849790
LP
67 pager_open_if_enabled();
68
89ffcd2a
LP
69 strv_sort(l);
70
71 STRV_FOREACH(i, l)
72 max_i = MAX(max_i, strlen(*i));
73
7b0b392f
LP
74 printf("%-*s %*s %-*s %-*s %-*s MACHINE\n",
75 (int) max_i, "NAME", 10, "PID", 15, "PROCESS", 16, "USER", 20, "CONNECTION");
89ffcd2a 76
de1c301e 77 STRV_FOREACH(i, l) {
5b12334d 78 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
de1c301e 79 _cleanup_free_ char *owner = NULL;
7b0b392f 80 sd_id128_t mid;
de1c301e 81
1f849790
LP
82 if (arg_no_unique && (*i)[0] == ':')
83 continue;
89ffcd2a
LP
84
85 printf("%-*s", (int) max_i, *i);
de1c301e 86
5b12334d 87 r = sd_bus_get_owner_creds(bus, *i, SD_BUS_CREDS_UID|SD_BUS_CREDS_PID|SD_BUS_CREDS_COMM, &creds);
89ffcd2a 88 if (r >= 0) {
5b12334d
LP
89 pid_t pid;
90 uid_t uid;
de1c301e 91
5b12334d
LP
92 r = sd_bus_creds_get_pid(creds, &pid);
93 if (r >= 0) {
94 const char *comm = NULL;
de1c301e 95
5b12334d 96 sd_bus_creds_get_comm(creds, &comm);
89ffcd2a 97
5b12334d
LP
98 printf(" %10lu %-15s", (unsigned long) pid, strna(comm));
99 } else
100 printf(" - - ");
89ffcd2a 101
5b12334d
LP
102 r = sd_bus_creds_get_uid(creds, &uid);
103 if (r >= 0) {
104 _cleanup_free_ char *u = NULL;
89ffcd2a 105
5b12334d
LP
106 u = uid_to_name(uid);
107 if (!u)
108 return log_oom();
89ffcd2a 109
5b12334d
LP
110 if (strlen(u) > 16)
111 u[16] = 0;
112
113 printf(" %-16s", u);
114 } else
115 printf(" - ");
89ffcd2a 116 } else
5b12334d
LP
117 printf(" - - - ");
118
89ffcd2a
LP
119
120 r = sd_bus_get_owner(bus, *i, &owner);
121 if (r >= 0)
7b0b392f 122 printf(" %-20s", owner);
89ffcd2a 123 else
7b0b392f
LP
124 printf(" - ");
125
126 r = sd_bus_get_owner_machine_id(bus, *i, &mid);
127 if (r >= 0) {
128 char m[SD_ID128_STRING_MAX];
129 printf(" %s\n", sd_id128_to_string(mid, m));
130 } else
89ffcd2a 131 printf(" -\n");
de1c301e
LP
132 }
133
1f849790
LP
134 return 0;
135}
136
137static int monitor(sd_bus *bus, char *argv[]) {
b51f299a 138 bool added_something = false;
1f849790
LP
139 char **i;
140 int r;
141
142 STRV_FOREACH(i, argv+1) {
143 _cleanup_free_ char *m = NULL;
144
145 if (!service_name_is_valid(*i)) {
146 log_error("Invalid service name '%s'", *i);
147 return -EINVAL;
148 }
149
150 m = strjoin("sender='", *i, "'", NULL);
151 if (!m)
152 return log_oom();
153
154 r = sd_bus_add_match(bus, m, NULL, NULL);
155 if (r < 0) {
156 log_error("Failed to add match: %s", strerror(-r));
157 return r;
158 }
b51f299a
LP
159
160 added_something = true;
1f849790
LP
161 }
162
163 STRV_FOREACH(i, arg_matches) {
164 r = sd_bus_add_match(bus, *i, NULL, NULL);
165 if (r < 0) {
166 log_error("Failed to add match: %s", strerror(-r));
167 return r;
168 }
b51f299a
LP
169
170 added_something = true;
171 }
172
173 if (!added_something) {
174 r = sd_bus_add_match(bus, "", NULL, NULL);
175 if (r < 0) {
176 log_error("Failed to add match: %s", strerror(-r));
177 return r;
178 }
1f849790
LP
179 }
180
181 for (;;) {
182 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
183
184 r = sd_bus_process(bus, &m);
185 if (r < 0) {
186 log_error("Failed to process bus: %s", strerror(-r));
187 return r;
188 }
189
190 if (m) {
c430fee6 191 bus_message_dump(m, stdout, true);
1f849790
LP
192 continue;
193 }
194
195 if (r > 0)
196 continue;
197
198 r = sd_bus_wait(bus, (uint64_t) -1);
199 if (r < 0) {
200 log_error("Failed to wait for bus: %s", strerror(-r));
201 return r;
202 }
203 }
204
205 return -EINVAL;
206}
207
208static int help(void) {
209
210 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
211 "Introspect the bus.\n\n"
d75edbd6
LP
212 " -h --help Show this help\n"
213 " --version Show package version\n"
a86a47ce 214 " --no-pager Do not pipe output into a pager\n"
d75edbd6
LP
215 " --system Connect to system bus\n"
216 " --user Connect to user bus\n"
217 " -H --host=[USER@]HOST Operate on remote host\n"
218 " -M --machine=CONTAINER Operate on local container\n"
219 " --address=ADDRESS Connect to bus specified by address\n"
220 " --no-unique Only show well-known names\n"
a86a47ce 221 " --match=MATCH Only show matching messages\n\n"
1f849790 222 "Commands:\n"
d75edbd6
LP
223 " list List bus names\n"
224 " monitor [SERVICE...] Show bus traffic\n",
1f849790
LP
225 program_invocation_short_name);
226
227 return 0;
228}
229
230static int parse_argv(int argc, char *argv[]) {
231
232 enum {
233 ARG_VERSION = 0x100,
234 ARG_NO_PAGER,
235 ARG_SYSTEM,
236 ARG_USER,
237 ARG_ADDRESS,
238 ARG_MATCH,
239 ARG_NO_UNIQUE
240 };
241
242 static const struct option options[] = {
243 { "help", no_argument, NULL, 'h' },
244 { "version", no_argument, NULL, ARG_VERSION },
245 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
246 { "system", no_argument, NULL, ARG_SYSTEM },
247 { "user", no_argument, NULL, ARG_USER },
248 { "address", required_argument, NULL, ARG_ADDRESS },
249 { "no-unique", no_argument, NULL, ARG_NO_UNIQUE },
250 { "match", required_argument, NULL, ARG_MATCH },
8fe12d88
LP
251 { "host", required_argument, NULL, 'H' },
252 { "machine", required_argument, NULL, 'M' },
eb9da376 253 {},
1f849790
LP
254 };
255
256 int c;
257
258 assert(argc >= 0);
259 assert(argv);
260
d75edbd6 261 while ((c = getopt_long(argc, argv, "hH:M:", options, NULL)) >= 0) {
1f849790
LP
262
263 switch (c) {
264
265 case 'h':
266 return help();
267
268 case ARG_VERSION:
269 puts(PACKAGE_STRING);
270 puts(SYSTEMD_FEATURES);
271 return 0;
272
273 case ARG_NO_PAGER:
274 arg_no_pager = true;
275 break;
276
277 case ARG_USER:
278 arg_user = true;
279 break;
280
281 case ARG_SYSTEM:
282 arg_user = false;
283 break;
284
285 case ARG_ADDRESS:
286 arg_address = optarg;
287 break;
288
289 case ARG_NO_UNIQUE:
290 arg_no_unique = true;
291 break;
292
293 case ARG_MATCH:
294 if (strv_extend(&arg_matches, optarg) < 0)
295 return log_oom();
296 break;
297
d75edbd6
LP
298 case 'H':
299 arg_transport = BUS_TRANSPORT_REMOTE;
300 arg_host = optarg;
301 break;
302
303 case 'M':
304 arg_transport = BUS_TRANSPORT_CONTAINER;
305 arg_host = optarg;
306 break;
307
1f849790
LP
308 case '?':
309 return -EINVAL;
310
311 default:
eb9da376 312 assert_not_reached("Unhandled option");
1f849790
LP
313 }
314 }
315
316 return 1;
317}
318
319static int busctl_main(sd_bus *bus, int argc, char *argv[]) {
320 assert(bus);
321
322 if (optind >= argc ||
323 streq(argv[optind], "list"))
324 return list_bus_names(bus, argv + optind);
325
326 if (streq(argv[optind], "monitor"))
327 return monitor(bus, argv + optind);
328
329 if (streq(argv[optind], "help"))
330 return help();
331
332 log_error("Unknown command '%s'", argv[optind]);
333 return -EINVAL;
334}
335
336int main(int argc, char *argv[]) {
337 _cleanup_bus_unref_ sd_bus *bus = NULL;
338 int r;
339
340 log_parse_environment();
341 log_open();
342
343 r = parse_argv(argc, argv);
344 if (r <= 0)
345 goto finish;
346
347 if (arg_address) {
348 r = sd_bus_new(&bus);
349 if (r < 0) {
350 log_error("Failed to allocate bus: %s", strerror(-r));
351 goto finish;
352 }
353
354 r = sd_bus_set_address(bus, arg_address);
355 if (r < 0) {
356 log_error("Failed to set address: %s", strerror(-r));
357 goto finish;
358 }
359
360 r = sd_bus_set_bus_client(bus, true);
361 if (r < 0) {
362 log_error("Failed to set bus client: %s", strerror(-r));
363 goto finish;
364 }
365
366 r = sd_bus_start(bus);
d75edbd6
LP
367 } else
368 r = bus_open_transport(arg_transport, arg_host, arg_user, &bus);
1f849790
LP
369
370 if (r < 0) {
371 log_error("Failed to connect to bus: %s", strerror(-r));
372 goto finish;
373 }
374
375 r = busctl_main(bus, argc, argv);
376
377finish:
378 pager_close();
d75edbd6 379
1f849790 380 strv_free(arg_matches);
de1c301e 381
de1c301e
LP
382 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
383}