1 // Copyright 2016 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <errno.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <unistd.h>
10
11 #include <zircon/syscalls.h>
12 #include <zircon/syscalls/log.h>
13
usage(void)14 void usage(void) {
15 fprintf(stderr,
16 "usage: dlog dump the zircon debug log\n"
17 "\n"
18 "options: -f don't exit, keep waiting for new messages\n"
19 " -p <pid> only show messages from specified pid\n"
20 " -t only show the text of messages (no metadata)\n"
21 " -h show help\n"
22 );
23 }
24
main(int argc,char ** argv)25 int main(int argc, char** argv) {
26 bool tail = false;
27 bool filter_pid = false;
28 bool plain = false;
29 zx_koid_t pid = 0;
30 zx_handle_t h;
31
32 while (argc > 1) {
33 if (!strcmp(argv[1], "-h")) {
34 usage();
35 return 0;
36 } else if (!strcmp(argv[1], "-f")) {
37 tail = true;
38 } else if (!strcmp(argv[1], "-t")) {
39 plain = true;
40 } else if (!strcmp(argv[1], "-p")) {
41 argc--;
42 argv++;
43 if (argc < 2) {
44 usage();
45 return -1;
46 }
47 errno = 0;
48 pid = strtoull(argv[1], NULL, 0);
49 if (errno) {
50 fprintf(stderr, "dlog: invalid pid\n");
51 return -1;
52 }
53 filter_pid = true;
54 } else {
55 usage();
56 return -1;
57 }
58 argc--;
59 argv++;
60 }
61
62 if (zx_debuglog_create(ZX_HANDLE_INVALID, ZX_LOG_FLAG_READABLE, &h) < 0) {
63 fprintf(stderr, "dlog: cannot open debug log\n");
64 return -1;
65 }
66
67 char buf[ZX_LOG_RECORD_MAX];
68 zx_log_record_t* rec = (zx_log_record_t*)buf;
69 for (;;) {
70 zx_status_t status;
71 if ((status = zx_debuglog_read(h, 0, rec, ZX_LOG_RECORD_MAX)) < 0) {
72 if ((status == ZX_ERR_SHOULD_WAIT) && tail) {
73 zx_object_wait_one(h, ZX_LOG_READABLE, ZX_TIME_INFINITE, NULL);
74 continue;
75 }
76 break;
77 }
78 if (filter_pid && (pid != rec->pid)) {
79 continue;
80 }
81 if (!plain) {
82 char tmp[32];
83 size_t len = snprintf(tmp, sizeof(tmp), "[%05d.%03d] ",
84 (int)(rec->timestamp / 1000000000ULL),
85 (int)((rec->timestamp / 1000000ULL) % 1000ULL));
86 write(1, tmp, (len > sizeof(tmp) ? sizeof(tmp) : len));
87 }
88 write(1, rec->data, rec->datalen);
89 if ((rec->datalen == 0) || (rec->data[rec->datalen - 1] != '\n')) {
90 write(1, "\n", 1);
91 }
92 }
93 return 0;
94 }
95