1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 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/>.
31 #include "bus-message.h"
32 #include "bus-internal.h"
35 static bool arg_no_pager = false;
36 static char *arg_address = NULL;
37 static bool arg_user = false;
38 static bool arg_no_unique = false;
39 static char **arg_matches = NULL;
41 static void pager_open_if_enabled(void) {
43 /* Cache result before we open the pager */
50 static int list_bus_names(sd_bus *bus, char **argv) {
51 _cleanup_strv_free_ char **l = NULL;
58 r = sd_bus_list_names(bus, &l);
60 log_error("Failed to list names: %s", strerror(-r));
64 pager_open_if_enabled();
69 max_i = MAX(max_i, strlen(*i));
71 printf("%-*s %*s %-*s %-*s CONNECTION\n",
72 (int) max_i, "NAME", 10, "PID", 15, "PROCESS", 16, "USER");
75 _cleanup_free_ char *owner = NULL;
79 if (arg_no_unique && (*i)[0] == ':')
82 printf("%-*s", (int) max_i, *i);
84 r = sd_bus_get_owner_pid(bus, *i, &pid);
86 _cleanup_free_ char *comm = NULL;
88 printf(" %10lu", (unsigned long) pid);
90 get_process_comm(pid, &comm);
91 printf(" %-15s", strna(comm));
95 r = sd_bus_get_owner_uid(bus, *i, &uid);
97 _cleanup_free_ char *u = NULL;
110 r = sd_bus_get_owner(bus, *i, &owner);
112 printf(" %s\n", owner);
120 static int monitor(sd_bus *bus, char *argv[]) {
124 STRV_FOREACH(i, argv+1) {
125 _cleanup_free_ char *m = NULL;
127 if (!service_name_is_valid(*i)) {
128 log_error("Invalid service name '%s'", *i);
132 m = strjoin("sender='", *i, "'", NULL);
136 r = sd_bus_add_match(bus, m, NULL, NULL);
138 log_error("Failed to add match: %s", strerror(-r));
143 STRV_FOREACH(i, arg_matches) {
144 r = sd_bus_add_match(bus, *i, NULL, NULL);
146 log_error("Failed to add match: %s", strerror(-r));
152 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
154 r = sd_bus_process(bus, &m);
156 log_error("Failed to process bus: %s", strerror(-r));
168 r = sd_bus_wait(bus, (uint64_t) -1);
170 log_error("Failed to wait for bus: %s", strerror(-r));
178 static int help(void) {
180 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
181 "Introspect the bus.\n\n"
182 " -h --help Show this help\n"
183 " --version Show package version\n"
184 " --system Connect to system bus\n"
185 " --user Connect to user bus\n"
186 " --address=ADDRESS Connect to bus specified by address\n"
187 " --no-unique Only show well-known names\n"
188 " --match=MATCH Only show matching messages\n"
189 " --no-pager Do not pipe output into a pager\n\n"
191 " list List bus names\n"
192 " monitor [SERVICE...] Show bus traffic\n",
193 program_invocation_short_name);
198 static int parse_argv(int argc, char *argv[]) {
210 static const struct option options[] = {
211 { "help", no_argument, NULL, 'h' },
212 { "version", no_argument, NULL, ARG_VERSION },
213 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
214 { "system", no_argument, NULL, ARG_SYSTEM },
215 { "user", no_argument, NULL, ARG_USER },
216 { "address", required_argument, NULL, ARG_ADDRESS },
217 { "no-unique", no_argument, NULL, ARG_NO_UNIQUE },
218 { "match", required_argument, NULL, ARG_MATCH },
219 { NULL, 0, NULL, 0 },
227 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) {
235 puts(PACKAGE_STRING);
236 puts(SYSTEMD_FEATURES);
252 arg_address = optarg;
256 arg_no_unique = true;
260 if (strv_extend(&arg_matches, optarg) < 0)
268 log_error("Unknown option code %c", c);
276 static int busctl_main(sd_bus *bus, int argc, char *argv[]) {
279 if (optind >= argc ||
280 streq(argv[optind], "list"))
281 return list_bus_names(bus, argv + optind);
283 if (streq(argv[optind], "monitor"))
284 return monitor(bus, argv + optind);
286 if (streq(argv[optind], "help"))
289 log_error("Unknown command '%s'", argv[optind]);
293 int main(int argc, char *argv[]) {
294 _cleanup_bus_unref_ sd_bus *bus = NULL;
297 log_parse_environment();
300 r = parse_argv(argc, argv);
305 r = sd_bus_new(&bus);
307 log_error("Failed to allocate bus: %s", strerror(-r));
311 r = sd_bus_set_address(bus, arg_address);
313 log_error("Failed to set address: %s", strerror(-r));
317 r = sd_bus_set_bus_client(bus, true);
319 log_error("Failed to set bus client: %s", strerror(-r));
323 r = sd_bus_start(bus);
325 r = sd_bus_open_user(&bus);
327 r = sd_bus_open_system(&bus);
330 log_error("Failed to connect to bus: %s", strerror(-r));
334 r = busctl_main(bus, argc, argv);
338 strv_free(arg_matches);
340 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;