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 14void 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 25int 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