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