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/>.
22 #include <sys/capability.h>
25 #include "capability.h"
29 #include "bus-message.h"
30 #include "bus-internal.h"
34 static char *indent(unsigned level) {
37 p = new(char, 2 + level + 1);
42 memset(p + 2, '\t', level);
48 int bus_message_dump(sd_bus_message *m, FILE *f, bool with_header) {
59 "%s%s%sType=%s%s%s Endian=%c Flags=%u Version=%u",
60 m->header->type == SD_BUS_MESSAGE_METHOD_ERROR ? ansi_highlight_red() :
61 m->header->type == SD_BUS_MESSAGE_METHOD_RETURN ? ansi_highlight_green() :
62 m->header->type != SD_BUS_MESSAGE_SIGNAL ? ansi_highlight() : "", draw_special_char(DRAW_TRIANGULAR_BULLET), ansi_highlight_off(),
63 ansi_highlight(), bus_message_type_to_string(m->header->type), ansi_highlight_off(),
68 /* Display synthetic message serial number in a more readable
69 * format than (uint32_t) -1 */
70 if (BUS_MESSAGE_SERIAL(m) == 0xFFFFFFFFULL)
71 fprintf(f, " Serial=-1");
73 fprintf(f, " Serial=%u", BUS_MESSAGE_SERIAL(m));
75 if (m->reply_serial != 0)
76 fprintf(f, " ReplySerial=%u", m->reply_serial);
81 fprintf(f, " Sender=%s%s%s", ansi_highlight(), m->sender, ansi_highlight_off());
83 fprintf(f, " Destination=%s%s%s", ansi_highlight(), m->destination, ansi_highlight_off());
85 fprintf(f, " Path=%s%s%s", ansi_highlight(), m->path, ansi_highlight_off());
87 fprintf(f, " Interface=%s%s%s", ansi_highlight(), m->interface, ansi_highlight_off());
89 fprintf(f, " Member=%s%s%s", ansi_highlight(), m->member, ansi_highlight_off());
91 if (m->sender || m->destination || m->path || m->interface || m->member)
94 if (sd_bus_error_is_set(&m->error))
97 " ErrorMessage=%s\"%s\"%s\n",
98 ansi_highlight_red(), strna(m->error.name), ansi_highlight_off(),
99 ansi_highlight_red(), strna(m->error.message), ansi_highlight_off());
101 if (m->monotonic != 0)
102 fprintf(f, " Monotonic=%llu", (unsigned long long) m->monotonic);
103 if (m->realtime != 0)
104 fprintf(f, " Realtime=%llu", (unsigned long long) m->realtime);
106 if (m->monotonic != 0 || m->realtime != 0)
109 bus_creds_dump(&m->creds, f);
112 r = sd_bus_message_rewind(m, true);
114 log_error("Failed to rewind: %s", strerror(-r));
118 fprintf(f, " MESSAGE \"%s\" {\n", strempty(m->root_container.signature));
121 _cleanup_free_ char *prefix = NULL;
122 const char *contents = NULL;
137 r = sd_bus_message_peek_type(m, &type, &contents);
139 log_error("Failed to peek type: %s", strerror(-r));
147 r = sd_bus_message_exit_container(m);
149 log_error("Failed to exit container: %s", strerror(-r));
155 prefix = indent(level);
159 fprintf(f, "%s};\n", prefix);
163 prefix = indent(level);
167 if (bus_type_is_container(type) > 0) {
168 r = sd_bus_message_enter_container(m, type, contents);
170 log_error("Failed to enter container: %s", strerror(-r));
174 if (type == SD_BUS_TYPE_ARRAY)
175 fprintf(f, "%sARRAY \"%s\" {\n", prefix, contents);
176 else if (type == SD_BUS_TYPE_VARIANT)
177 fprintf(f, "%sVARIANT \"%s\" {\n", prefix, contents);
178 else if (type == SD_BUS_TYPE_STRUCT)
179 fprintf(f, "%sSTRUCT \"%s\" {\n", prefix, contents);
180 else if (type == SD_BUS_TYPE_DICT_ENTRY)
181 fprintf(f, "%sDICT_ENTRY \"%s\" {\n", prefix, contents);
188 r = sd_bus_message_read_basic(m, type, &basic);
190 log_error("Failed to get basic: %s", strerror(-r));
198 case SD_BUS_TYPE_BYTE:
199 fprintf(f, "%sBYTE %s%u%s;\n", prefix, ansi_highlight(), basic.u8, ansi_highlight_off());
202 case SD_BUS_TYPE_BOOLEAN:
203 fprintf(f, "%sBOOLEAN %s%s%s;\n", prefix, ansi_highlight(), yes_no(basic.i), ansi_highlight_off());
206 case SD_BUS_TYPE_INT16:
207 fprintf(f, "%sINT16 %s%i%s;\n", prefix, ansi_highlight(), basic.s16, ansi_highlight_off());
210 case SD_BUS_TYPE_UINT16:
211 fprintf(f, "%sUINT16 %s%u%s;\n", prefix, ansi_highlight(), basic.u16, ansi_highlight_off());
214 case SD_BUS_TYPE_INT32:
215 fprintf(f, "%sINT32 %s%i%s;\n", prefix, ansi_highlight(), basic.s32, ansi_highlight_off());
218 case SD_BUS_TYPE_UINT32:
219 fprintf(f, "%sUINT32 %s%u%s;\n", prefix, ansi_highlight(), basic.u32, ansi_highlight_off());
222 case SD_BUS_TYPE_INT64:
223 fprintf(f, "%sINT64 %s%lli%s;\n", prefix, ansi_highlight(), (long long) basic.s64, ansi_highlight_off());
226 case SD_BUS_TYPE_UINT64:
227 fprintf(f, "%sUINT64 %s%llu%s;\n", prefix, ansi_highlight(), (unsigned long long) basic.u64, ansi_highlight_off());
230 case SD_BUS_TYPE_DOUBLE:
231 fprintf(f, "%sDOUBLE %s%g%s;\n", prefix, ansi_highlight(), basic.d64, ansi_highlight_off());
234 case SD_BUS_TYPE_STRING:
235 fprintf(f, "%sSTRING \"%s%s%s\";\n", prefix, ansi_highlight(), basic.string, ansi_highlight_off());
238 case SD_BUS_TYPE_OBJECT_PATH:
239 fprintf(f, "%sOBJECT_PATH \"%s%s%s\";\n", prefix, ansi_highlight(), basic.string, ansi_highlight_off());
242 case SD_BUS_TYPE_SIGNATURE:
243 fprintf(f, "%sSIGNATURE \"%s%s%s\";\n", prefix, ansi_highlight(), basic.string, ansi_highlight_off());
246 case SD_BUS_TYPE_UNIX_FD:
247 fprintf(f, "%sUNIX_FD %s%i%s;\n", prefix, ansi_highlight(), basic.i, ansi_highlight_off());
251 assert_not_reached("Unknown basic type.");
255 fprintf(f, " };\n\n");
259 static void dump_capabilities(
263 int (*has)(sd_bus_creds *c, int capability)) {
265 unsigned long i, last_cap;
279 fprintf(f, " %s=", name);
280 last_cap = cap_last_cap();
289 fputs(cap_to_name(i), f);
304 int bus_creds_dump(sd_bus_creds *c, FILE *f) {
305 bool audit_sessionid_is_set = false, audit_loginuid_is_set = false;
306 const char *u = NULL, *uu = NULL, *s = NULL, *sl = NULL;
307 uid_t owner, audit_loginuid;
308 uint32_t audit_sessionid;
309 char **cmdline = NULL, **well_known = NULL;
317 if (c->mask & SD_BUS_CREDS_PID)
318 fprintf(f, " PID=%lu", (unsigned long) c->pid);
319 if (c->mask & SD_BUS_CREDS_PID_STARTTIME)
320 fprintf(f, " PIDStartTime=%llu", (unsigned long long) c->pid_starttime);
321 if (c->mask & SD_BUS_CREDS_TID)
322 fprintf(f, " TID=%lu", (unsigned long) c->tid);
323 if (c->mask & SD_BUS_CREDS_UID)
324 fprintf(f, " UID=%lu", (unsigned long) c->uid);
325 r = sd_bus_creds_get_owner_uid(c, &owner);
327 fprintf(f, " OwnerUID=%lu", (unsigned long) owner);
328 if (c->mask & SD_BUS_CREDS_GID)
329 fprintf(f, " GID=%lu", (unsigned long) c->gid);
331 if ((c->mask & (SD_BUS_CREDS_PID|SD_BUS_CREDS_PID_STARTTIME|SD_BUS_CREDS_TID|SD_BUS_CREDS_UID|SD_BUS_CREDS_GID)) || r >= 0)
334 if (c->mask & SD_BUS_CREDS_EXE)
335 fprintf(f, " Exe=%s", c->exe);
336 if (c->mask & SD_BUS_CREDS_COMM)
337 fprintf(f, " Comm=%s", c->comm);
338 if (c->mask & SD_BUS_CREDS_TID_COMM)
339 fprintf(f, " TIDComm=%s", c->tid_comm);
340 if (c->mask & SD_BUS_CREDS_SELINUX_CONTEXT)
341 fprintf(f, " Label=%s", c->label);
343 if (c->mask & (SD_BUS_CREDS_EXE|SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM|SD_BUS_CREDS_SELINUX_CONTEXT))
346 if (sd_bus_creds_get_cmdline(c, &cmdline) >= 0) {
349 fputs(" CommandLine={", f);
350 STRV_FOREACH(i, cmdline) {
360 if (c->mask & SD_BUS_CREDS_CGROUP)
361 fprintf(f, " CGroup=%s", c->cgroup);
362 sd_bus_creds_get_unit(c, &u);
364 fprintf(f, " Unit=%s", u);
365 sd_bus_creds_get_user_unit(c, &uu);
367 fprintf(f, " UserUnit=%s", uu);
368 sd_bus_creds_get_slice(c, &sl);
370 fprintf(f, " Slice=%s", sl);
371 sd_bus_creds_get_session(c, &s);
373 fprintf(f, " Session=%s", s);
375 if ((c->mask & SD_BUS_CREDS_CGROUP) || u || uu || sl || s)
378 if (sd_bus_creds_get_audit_login_uid(c, &audit_loginuid) >= 0) {
379 audit_loginuid_is_set = true;
380 fprintf(f, " AuditLoginUID=%lu", (unsigned long) audit_loginuid);
382 if (sd_bus_creds_get_audit_session_id(c, &audit_sessionid) >= 0) {
383 audit_sessionid_is_set = true;
384 fprintf(f, " AuditSessionID=%lu", (unsigned long) audit_sessionid);
387 if (audit_loginuid_is_set || audit_sessionid_is_set)
390 if (c->mask & SD_BUS_CREDS_UNIQUE_NAME)
391 fprintf(f, " UniqueName=%s", c->unique_name);
393 if (sd_bus_creds_get_well_known_names(c, &well_known) >= 0) {
396 fputs(" WellKnownNames={", f);
397 STRV_FOREACH(i, well_known) {
407 if (c->mask & SD_BUS_CREDS_UNIQUE_NAME || well_known)
410 dump_capabilities(c, f, "EffectiveCapabilities", sd_bus_creds_has_effective_cap);
411 dump_capabilities(c, f, "PermittedCapabilities", sd_bus_creds_has_permitted_cap);
412 dump_capabilities(c, f, "InheritableCapabilities", sd_bus_creds_has_inheritable_cap);
413 dump_capabilities(c, f, "BoundingCapabilities", sd_bus_creds_has_bounding_cap);