blob: 1dae863f4330c0c3a29aae73b8427b61b3276fa5 [file] [log] [blame]
--- 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) {