chiark / gitweb /
bus: add missing dump.[ch]
[elogind.git] / src / libsystemd-bus / bus-dump.c
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
22 #include <sys/capability.h>
23
24 #include "util.h"
25 #include "capability.h"
26 #include "strv.h"
27
28 #include "bus-message.h"
29 #include "bus-internal.h"
30 #include "bus-type.h"
31 #include "bus-dump.h"
32
33 int bus_message_dump(sd_bus_message *m, FILE *f, bool with_header) {
34         const char *u = NULL, *uu = NULL, *s = NULL;
35         char **cmdline = NULL;
36         unsigned level = 1;
37         int r;
38         uid_t owner, audit_loginuid;
39         uint32_t audit_sessionid;
40
41         assert(m);
42
43         if (!f)
44                 f = stdout;
45
46         if (with_header) {
47                 fprintf(f,
48                         "%sEndian=%c  Type=%s%s%s  Flags=%u  Version=%u  Serial=%u ",
49                         draw_special_char(DRAW_TRIANGULAR_BULLET),
50                         m->header->endian,
51                         ansi_highlight(), bus_message_type_to_string(m->header->type), ansi_highlight_off(),
52                         m->header->flags,
53                         m->header->version,
54                         BUS_MESSAGE_SERIAL(m));
55
56                 if (m->reply_serial != 0)
57                         fprintf(f, "  ReplySerial=%u", m->reply_serial);
58
59                 fputs("\n", f);
60
61                 if (m->sender)
62                         fprintf(f, "  Sender=%s%s%s", ansi_highlight(), m->sender, ansi_highlight_off());
63                 if (m->destination)
64                         fprintf(f, "  Destination=%s%s%s", ansi_highlight(), m->destination, ansi_highlight_off());
65                 if (m->path)
66                         fprintf(f, "  Path=%s%s%s", ansi_highlight(), m->path, ansi_highlight_off());
67                 if (m->interface)
68                         fprintf(f, "  Interface=%s%s%s", ansi_highlight(), m->interface, ansi_highlight_off());
69                 if (m->member)
70                         fprintf(f, "  Member=%s%s%s", ansi_highlight(), m->member, ansi_highlight_off());
71
72                 if (m->sender || m->destination || m->path || m->interface || m->member)
73                         fputs("\n", f);
74
75                 if (sd_bus_error_is_set(&m->error))
76                         fprintf(f,
77                                 "  ErrorName=%s%s%s"
78                                 "  ErrorMessage=%s\"%s\"%s\n",
79                                 ansi_highlight_red(), strna(m->error.name), ansi_highlight_off(),
80                                 ansi_highlight_red(), strna(m->error.message), ansi_highlight_off());
81
82                 if (m->pid != 0)
83                         fprintf(f, "  PID=%lu", (unsigned long) m->pid);
84                 if (m->pid_starttime != 0)
85                         fprintf(f, "  PIDStartTime=%llu", (unsigned long long) m->pid_starttime);
86                 if (m->tid != 0)
87                         fprintf(f, "  TID=%lu", (unsigned long) m->tid);
88                 if (m->uid_valid)
89                         fprintf(f, "  UID=%lu", (unsigned long) m->uid);
90                 r = sd_bus_message_get_owner_uid(m, &owner);
91                 if (r >= 0)
92                         fprintf(f, "  OwnerUID=%lu", (unsigned long) owner);
93                 if (m->gid_valid)
94                         fprintf(f, "  GID=%lu", (unsigned long) m->gid);
95
96                 if (m->pid != 0 || m->pid_starttime != 0 || m->tid != 0 || m->uid_valid || r >= 0 || m->gid_valid)
97                         fputs("\n", f);
98
99                 if (m->monotonic != 0)
100                         fprintf(f, "  Monotonic=%llu", (unsigned long long) m->monotonic);
101                 if (m->realtime != 0)
102                         fprintf(f, "  Realtime=%llu", (unsigned long long) m->realtime);
103
104                 if (m->monotonic != 0 || m->realtime != 0)
105                         fputs("\n", f);
106
107                 if (m->exe)
108                         fprintf(f, "  Exe=%s", m->exe);
109                 if (m->comm)
110                         fprintf(f, "  Comm=%s", m->comm);
111                 if (m->tid_comm)
112                         fprintf(f, "  TIDComm=%s", m->tid_comm);
113                 if (m->label)
114                         fprintf(f, "  Label=%s", m->label);
115
116                 if (m->exe || m->comm || m->tid_comm || m->label)
117                         fputs("\n", f);
118
119                 if (sd_bus_message_get_cmdline(m, &cmdline) >= 0) {
120                         char **c;
121
122                         fputs("  CommandLine=[", f);
123                         STRV_FOREACH(c, cmdline) {
124                                 if (c != cmdline)
125                                         fputc(' ', f);
126
127                                 fputs(*c, f);
128                         }
129
130                         fputs("]\n", f);
131                 }
132
133                 if (m->cgroup)
134                         fprintf(f, "  CGroup=%s\n", m->cgroup);
135
136                 sd_bus_message_get_unit(m, &u);
137                 if (u)
138                         fprintf(f, "  Unit=%s", u);
139                 sd_bus_message_get_user_unit(m, &uu);
140                 if (uu)
141                         fprintf(f, "  UserUnit=%s", uu);
142                 sd_bus_message_get_session(m, &s);
143                 if (s)
144                         fprintf(f, "  Session=%s", s);
145                 if (sd_bus_message_get_audit_loginuid(m, &audit_loginuid) >= 0)
146                         fprintf(f, "  AuditLoginUID=%lu", (unsigned long) audit_loginuid);
147                 if (sd_bus_message_get_audit_sessionid(m, &audit_sessionid) >= 0)
148                         fprintf(f, "  AuditSessionID=%lu", (unsigned long) audit_sessionid);
149
150                 if (u || uu || s || audit_loginuid || audit_sessionid)
151                         fputs("\n", f);
152
153                 r = sd_bus_message_has_effective_cap(m, 0);
154                 if (r >= 0) {
155                         unsigned long c, last_cap;
156
157                         fprintf(f, "  Capabilities=%s", r ? cap_to_name(0) : "");
158
159                         last_cap = cap_last_cap();
160                         for (c = 0; c < last_cap; c++) {
161                                 r = sd_bus_message_has_effective_cap(m, c);
162                                 if (r > 0)
163                                         fprintf(f, "|%s", cap_to_name(c));
164                         }
165                 }
166         }
167
168         r = sd_bus_message_rewind(m, true);
169         if (r < 0) {
170                 log_error("Failed to rewind: %s", strerror(-r));
171                 return r;
172         }
173
174         fprintf(f, "MESSAGE \"%s\" {\n", strempty(m->root_container.signature));
175
176         for(;;) {
177                 _cleanup_free_ char *prefix = NULL;
178                 const char *contents = NULL;
179                 char type;
180                 union {
181                         uint8_t u8;
182                         uint16_t u16;
183                         int16_t s16;
184                         uint32_t u32;
185                         int32_t s32;
186                         uint64_t u64;
187                         int64_t s64;
188                         double d64;
189                         const char *string;
190                         int i;
191                 } basic;
192
193                 r = sd_bus_message_peek_type(m, &type, &contents);
194                 if (r < 0) {
195                         log_error("Failed to peek type: %s", strerror(-r));
196                         return r;
197                 }
198
199                 if (r == 0) {
200                         if (level <= 1)
201                                 break;
202
203                         r = sd_bus_message_exit_container(m);
204                         if (r < 0) {
205                                 log_error("Failed to exit container: %s", strerror(-r));
206                                 return r;
207                         }
208
209                         level--;
210
211                         prefix = strrep("\t", level);
212                         if (!prefix)
213                                 return log_oom();
214
215                         fprintf(f, "%s};\n", prefix);
216                         continue;
217                 }
218
219                 prefix = strrep("\t", level);
220                 if (!prefix)
221                         return log_oom();
222
223                 if (bus_type_is_container(type) > 0) {
224                         r = sd_bus_message_enter_container(m, type, contents);
225                         if (r < 0) {
226                                 log_error("Failed to enter container: %s", strerror(-r));
227                                 return r;
228                         }
229
230                         if (type == SD_BUS_TYPE_ARRAY)
231                                 fprintf(f, "%sARRAY \"%s\" {\n", prefix, contents);
232                         else if (type == SD_BUS_TYPE_VARIANT)
233                                 fprintf(f, "%sVARIANT \"%s\" {\n", prefix, contents);
234                         else if (type == SD_BUS_TYPE_STRUCT)
235                                 fprintf(f, "%sSTRUCT \"%s\" {\n", prefix, contents);
236                         else if (type == SD_BUS_TYPE_DICT_ENTRY)
237                                 fprintf(f, "%sDICT_ENTRY \"%s\" {\n", prefix, contents);
238
239                         level ++;
240
241                         continue;
242                 }
243
244                 r = sd_bus_message_read_basic(m, type, &basic);
245                 if (r < 0) {
246                         log_error("Failed to get basic: %s", strerror(-r));
247                         return r;
248                 }
249
250                 assert(r > 0);
251
252                 switch (type) {
253
254                 case SD_BUS_TYPE_BYTE:
255                         fprintf(f, "%sBYTE %s%u%s;\n", prefix, ansi_highlight(), basic.u8, ansi_highlight_off());
256                         break;
257
258                 case SD_BUS_TYPE_BOOLEAN:
259                         fprintf(f, "%sBOOLEAN %s%s%s;\n", prefix, ansi_highlight(), yes_no(basic.i), ansi_highlight_off());
260                         break;
261
262                 case SD_BUS_TYPE_INT16:
263                         fprintf(f, "%sINT16 %s%i%s;\n", prefix, ansi_highlight(), basic.s16, ansi_highlight_off());
264                         break;
265
266                 case SD_BUS_TYPE_UINT16:
267                         fprintf(f, "%sUINT16 %s%u%s;\n", prefix, ansi_highlight(), basic.u16, ansi_highlight_off());
268                         break;
269
270                 case SD_BUS_TYPE_INT32:
271                         fprintf(f, "%sINT32 %s%i%s;\n", prefix, ansi_highlight(), basic.s32, ansi_highlight_off());
272                         break;
273
274                 case SD_BUS_TYPE_UINT32:
275                         fprintf(f, "%sUINT32 %s%u%s;\n", prefix, ansi_highlight(), basic.u32, ansi_highlight_off());
276                         break;
277
278                 case SD_BUS_TYPE_INT64:
279                         fprintf(f, "%sINT64 %s%lli%s;\n", prefix, ansi_highlight(), (long long) basic.s64, ansi_highlight_off());
280                         break;
281
282                 case SD_BUS_TYPE_UINT64:
283                         fprintf(f, "%sUINT64 %s%llu%s;\n", prefix, ansi_highlight(), (unsigned long long) basic.u64, ansi_highlight_off());
284                         break;
285
286                 case SD_BUS_TYPE_DOUBLE:
287                         fprintf(f, "%sDOUBLE %s%g%s;\n", prefix, ansi_highlight(), basic.d64, ansi_highlight_off());
288                         break;
289
290                 case SD_BUS_TYPE_STRING:
291                         fprintf(f, "%sSTRING \"%s%s%s\";\n", prefix, ansi_highlight(), basic.string, ansi_highlight_off());
292                         break;
293
294                 case SD_BUS_TYPE_OBJECT_PATH:
295                         fprintf(f, "%sOBJECT_PATH \"%s%s%s\";\n", prefix, ansi_highlight(), basic.string, ansi_highlight_off());
296                         break;
297
298                 case SD_BUS_TYPE_SIGNATURE:
299                         fprintf(f, "%sSIGNATURE \"%s%s%s\";\n", prefix, ansi_highlight(), basic.string, ansi_highlight_off());
300                         break;
301
302                 case SD_BUS_TYPE_UNIX_FD:
303                         fprintf(f, "%sUNIX_FD %s%i%s;\n", prefix, ansi_highlight(), basic.i, ansi_highlight_off());
304                         break;
305
306                 default:
307                         assert_not_reached("Unknown basic type.");
308                 }
309         }
310
311         fprintf(f, "};\n");
312         return 0;
313 }