| --- a/CMakeLists.txt |
| +++ b/CMakeLists.txt |
| @@ -63,7 +63,7 @@ INSTALL(TARGETS logd |
| ) |
| |
| ADD_EXECUTABLE(logread log/logread.c) |
| -TARGET_LINK_LIBRARIES(logread ubox ubus ${json} blobmsg_json) |
| +TARGET_LINK_LIBRARIES(logread log ubox ubus ${json} blobmsg_json) |
| INSTALL(TARGETS logread |
| RUNTIME DESTINATION sbin |
| ) |
| --- a/log/logread.c |
| +++ b/log/logread.c |
| @@ -14,6 +14,7 @@ |
| |
| #include <sys/types.h> |
| #include <sys/stat.h> |
| +#include <sys/klog.h> |
| |
| #include <fcntl.h> |
| #include <time.h> |
| @@ -22,6 +23,7 @@ |
| #include <unistd.h> |
| #include <sys/types.h> |
| #include <sys/socket.h> |
| +#include <include/log.h> |
| |
| #define SYSLOG_NAMES |
| #include <syslog.h> |
| @@ -35,10 +37,13 @@ |
| |
| #define LOGD_CONNECT_RETRY 10 |
| |
| +#define BLOG_DEFAULT_PROC "/proc/boot_log" |
| + |
| enum { |
| LOG_STDOUT, |
| LOG_FILE, |
| LOG_NET, |
| + LOG_DIAG, |
| }; |
| |
| enum { |
| @@ -63,7 +68,7 @@ static struct uloop_fd sender; |
| static regex_t regexp_preg; |
| static const char *log_file, *log_ip, *log_port, *log_prefix, *pid_file, *hostname, *regexp_pattern; |
| static int log_type = LOG_STDOUT; |
| -static int log_size, log_udp, log_follow, log_trailer_null = 0; |
| +static int log_size, log_udp, log_follow, log_trailer_null = 0, log_diag = 0; |
| static int log_timestamp; |
| static int logd_conn_tries = LOGD_CONNECT_RETRY; |
| static int facility_include; |
| @@ -129,7 +134,7 @@ static int log_notify(struct blob_attr * |
| char *c, *m; |
| int ret = 0; |
| |
| - if (sender.fd < 0) |
| + if (sender.fd < 0 && log_type != LOG_DIAG) |
| return 0; |
| |
| blobmsg_parse(log_policy, ARRAY_SIZE(log_policy), tb, blob_data(msg), blob_len(msg)); |
| @@ -205,6 +210,13 @@ static int log_notify(struct blob_attr * |
| sender.fd = -1; |
| uloop_timeout_set(&retry, 1000); |
| } |
| + } else if (log_type == LOG_DIAG) { |
| + snprintf(buf, sizeof(buf), "%s%s.%s%s %s\n", |
| + log_timestamp ? buf_ts : "", |
| + getcodetext(LOG_FAC(p) << 3, facilitynames), |
| + getcodetext(LOG_PRI(p), prioritynames), |
| + (blobmsg_get_u32(tb[LOG_SOURCE])) ? ("") : (" kernel:"), m); |
| + __android_log_printf(LOG_ID_MAIN, LOG_INFO_LEVEL, "%s", buf); |
| } else { |
| snprintf(buf, sizeof(buf), "%s %s%s.%s%s %s\n", |
| c, log_timestamp ? buf_ts : "", |
| @@ -237,6 +249,7 @@ static int usage(const char *prog) |
| " -Z <facility> ignore messages with given facility (0-23), repeatable\n" |
| " -f Follow log messages\n" |
| " -u Use UDP as the protocol\n" |
| + " -d Log to Diag\n" |
| " -t Add an extra timestamp\n" |
| " -0 Use \\0 instead of \\n as trailer when using TCP\n" |
| "\n", prog); |
| @@ -280,6 +293,121 @@ static void logread_fd_cb(struct ubus_re |
| ustream_fd_init(&test_fd, fd); |
| } |
| |
| + |
| +static void bootlog_cb(struct ustream *s, int bytes) |
| +{ |
| + struct ustream_buf *buf = s->r.head; |
| + char obuf[LOG_LINE_SIZE + 128]; |
| + char *newline, *str; |
| + int len; |
| + |
| + if (sender.fd < 0 && log_type != LOG_DIAG) |
| + return; |
| + |
| + do { |
| + str = ustream_get_read_buf(s, NULL); |
| + if (!str) |
| + break; |
| + newline = strchr(buf->data, '\n'); |
| + if (!newline) |
| + break; |
| + *newline = 0; |
| + len = newline + 1 - str; |
| + |
| + snprintf(obuf, sizeof(obuf), "%s\n", buf->data); |
| + if (log_type == LOG_FILE) |
| + write(sender.fd, obuf, strlen(obuf)); |
| + else if (log_type == LOG_DIAG) |
| + __android_log_printf(LOG_ID_MAIN, LOG_INFO_LEVEL, "%s", obuf); |
| + ustream_consume(s, len); |
| + } while (1); |
| +} |
| + |
| +static void get_klog(void) |
| +{ |
| + char obuf[LOG_LINE_SIZE + 128]; |
| + char *newline, *str; |
| + int len; |
| + char *klog_buf; |
| + |
| + if (sender.fd < 0 && log_type != LOG_DIAG) |
| + return; |
| + |
| + /* print dmesg */ |
| + len = klogctl(10, NULL, 0); /* read ring buffer size */ |
| + if (len < 16*1024) |
| + len = 16*1024; |
| + if (len > 16*1024*1024) |
| + len = 16*1024*1024; |
| + klog_buf = calloc(1, len);//malloc(len); |
| + len = klogctl(3, klog_buf, len); /* read ring buffer */ |
| + if (len <= 0) |
| + return; |
| + |
| + klog_buf[len] = '\0'; |
| + str = klog_buf; |
| + do { |
| + if (*str == '\0') |
| + break; |
| + |
| + newline = strchr(str, '\n'); |
| + if (!newline) |
| + break; |
| + *newline = 0; |
| + len = newline + 1 - str; |
| + |
| + snprintf(obuf, sizeof(obuf), "%s\n", str); |
| + if (log_type == LOG_FILE) |
| + write(sender.fd, obuf, strlen(obuf)); |
| + else if (log_type == LOG_DIAG) |
| + __android_log_printf(LOG_ID_MAIN, LOG_INFO_LEVEL, "%s", obuf); |
| + str = newline + 1; |
| + } while (1); |
| + |
| + free(klog_buf); |
| + |
| + if (log_type == LOG_FILE) |
| + fsync(sender.fd); |
| +} |
| + |
| +static void bootlog_notify_state(struct ustream *s) |
| +{ |
| + struct ustream_fd *sf = container_of(s, struct ustream_fd, stream); |
| + |
| + if (!s->eof) |
| + return; |
| + |
| + /* get dmesg log */ |
| + get_klog(); |
| + |
| + ustream_free(s); |
| + close(sf->fd.fd); |
| +} |
| + |
| +static struct ustream_fd bootlog = { |
| + .stream.string_data = true, |
| + .stream.notify_read = bootlog_cb, |
| + .stream.notify_state = bootlog_notify_state, |
| +}; |
| + |
| +static int |
| +bootlog_open(void) |
| +{ |
| + int fd; |
| + |
| + if (!log_diag && !log_file) |
| + return 0; |
| + |
| + fd = open(BLOG_DEFAULT_PROC, O_RDONLY | O_NONBLOCK); |
| + if (fd < 0) { |
| + fprintf(stderr, "Failed to open %s\n", BLOG_DEFAULT_PROC); |
| + return -1; |
| + } |
| + fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC); |
| + ustream_fd_init(&bootlog, fd); |
| + return 0; |
| +} |
| + |
| static void logread_setup_output(void) |
| { |
| if (sender.fd || sender.cb) |
| @@ -298,6 +426,8 @@ static void logread_setup_output(void) |
| fprintf(stderr, "failed to open %s: %m\n", log_file); |
| exit(-1); |
| } |
| + } else if (log_diag) { |
| + log_type = LOG_DIAG; |
| } else { |
| sender.fd = STDOUT_FILENO; |
| } |
| @@ -313,7 +443,8 @@ int main(int argc, char **argv) |
| |
| signal(SIGPIPE, SIG_IGN); |
| |
| - while ((ch = getopt(argc, argv, "u0fcs:l:z:Z:r:F:p:S:P:h:e:t")) != -1) { |
| + set_service_log_tag("SYSLOG"); |
| + while ((ch = getopt(argc, argv, "du0fcs:l:z:Z:r:F:p:S:P:h:e:t")) != -1) { |
| switch (ch) { |
| case 'u': |
| log_udp = 1; |
| @@ -328,6 +459,9 @@ int main(int argc, char **argv) |
| log_ip = optarg++; |
| log_port = argv[optind++]; |
| break; |
| + case 'd': |
| + log_diag = 1; |
| + break; |
| case 'F': |
| log_file = optarg; |
| break; |
| @@ -381,6 +515,8 @@ int main(int argc, char **argv) |
| } |
| ubus_add_uloop(ctx); |
| |
| + bootlog_open(); |
| + |
| if (log_follow && pid_file) { |
| FILE *fp = fopen(pid_file, "w+"); |
| if (fp) { |