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