| diff --git a/system/core/liblog/logger_write.c b/system/core/liblog/logger_write.c |
| index b802ed7..3061862 100644 |
| --- a/system/core/liblog/logger_write.c |
| +++ b/system/core/liblog/logger_write.c |
| @@ -31,6 +31,14 @@ |
| #include <private/android_filesystem_config.h> |
| #include <private/android_logger.h> |
| |
| +#define __REDIRECT_TO_SYSLOGD__ |
| + |
| +#if defined(__REDIRECT_TO_SYSLOGD__) |
| +#include <syslog.h> |
| +#include <sys/syscall.h> |
| +#include <unistd.h> |
| +#endif |
| + |
| #include "config_write.h" |
| #include "log_portability.h" |
| #include "logger.h" |
| @@ -186,8 +194,187 @@ static inline uint32_t get4LE(const uint8_t* src) |
| return src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24); |
| } |
| |
| +#if defined(__REDIRECT_TO_SYSLOGD__) |
| +static int filterPriAndSysPri (android_LogPriority pri, int *sys_pri) |
| +{ |
| + switch (pri) { |
| + case ANDROID_LOG_DEBUG: |
| + *sys_pri = LOG_DEBUG; |
| + return 3; |
| + case ANDROID_LOG_INFO: |
| + *sys_pri = LOG_INFO; |
| + return 4; |
| + case ANDROID_LOG_WARN: |
| + *sys_pri = LOG_WARNING; |
| + return 5; |
| + case ANDROID_LOG_ERROR: |
| + *sys_pri = LOG_ERR; |
| + return 6; |
| + case ANDROID_LOG_FATAL: |
| + *sys_pri = LOG_CRIT; |
| + return 7; |
| + case ANDROID_LOG_SILENT: |
| + *sys_pri = LOG_EMERG; |
| + return 8; |
| + |
| + case ANDROID_LOG_DEFAULT: |
| + case ANDROID_LOG_UNKNOWN: |
| + default: |
| + *sys_pri = LOG_INFO; |
| + return 1; |
| + } |
| +} |
| + |
| +static char *filterLogId(log_id_t log_id) |
| +{ |
| + switch (log_id) { |
| + case LOG_ID_MAIN: |
| + return "MAIN"; |
| + case LOG_ID_RADIO : |
| + return "RADIO"; |
| + case LOG_ID_EVENTS: |
| + return "EVENT"; |
| + case LOG_ID_SYSTEM: |
| + return "SYSTEM"; |
| + default: |
| + return "UNKOWN"; |
| + } |
| +} |
| + |
| +/* |
| + * Extract an 8-byte value from a byte stream. |
| + */ |
| +static inline uint64_t get8LE(const uint8_t* src) |
| +{ |
| + uint32_t low, high; |
| + |
| + low = src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24); |
| + high = src[4] | (src[5] << 8) | (src[6] << 16) | (src[7] << 24); |
| + return ((long long) high << 32) | (long long) low; |
| +} |
| + |
| +static char filterEvtType(char type, char *buf, void *payload, ssize_t len) |
| +{ |
| + switch(type) { |
| + case EVENT_TYPE_INT: |
| + sprintf(buf, "%d", get4LE(payload)); |
| + return 'I'; |
| + case EVENT_TYPE_LONG: |
| + sprintf(buf, "%lld", get8LE(payload)); |
| + return 'L'; |
| + case EVENT_TYPE_STRING: |
| + snprintf(buf, len, "%s", payload); |
| + buf[len] = '\0'; |
| + return 'S'; |
| + default: /* not support */ |
| + sprintf(buf, "?"); |
| + return '?'; |
| + } |
| +} |
| +#endif |
| + |
| + |
| static int __write_to_log_daemon(log_id_t log_id, struct iovec *vec, size_t nr) |
| { |
| +#if defined(__REDIRECT_TO_SYSLOGD__) |
| + int ret; |
| + size_t totalLen = 0, defaultLen = 512, prefixLen; |
| + int write_allocate = 0; |
| + int sys_pri = LOG_INFO; |
| + char *writeBuf = NULL; |
| + char defaultBuf[512]; |
| + char prefixBuf[128]; |
| + char *idChar; |
| + int priChar; |
| + |
| + // for main, system, radio |
| + ssize_t msg_len = 0; |
| + int priority = ANDROID_LOG_INFO; |
| + char *tag, *msg; |
| + |
| + // for event |
| + int32_t etag; |
| + char type; |
| + void *payload; |
| + |
| + // ------------------------------------------------------------------ |
| + // get log id |
| + idChar = filterLogId(log_id); |
| + |
| +#if 0 //disable event logid |
| + if(log_id == LOG_ID_EVENTS) { /* event type */ |
| + if(nr == 2) { // __android_log_bwrite |
| + etag = *((int32_t *)vec[0].iov_base); |
| + type = EVENT_TYPE_INT; |
| + payload = (void *)vec[1].iov_base; |
| + msg_len = vec[1].iov_len; |
| + } else { // __android_log_btwrite |
| + etag = *((int32_t *)vec[0].iov_base); |
| + type = *((char *)vec[1].iov_base); |
| + |
| + if(!strcmp(&type, "")) |
| + type = EVENT_TYPE_STRING; |
| + |
| + payload = (void *)vec[2].iov_base; |
| + msg_len = vec[2].iov_len; |
| + } |
| + |
| + // get type char |
| + priChar = filterEvtType(type, prefixBuf, payload, msg_len); |
| + |
| + // format prefix (brief format) |
| + snprintf(defaultBuf, sizeof(defaultBuf), |
| + "<%c>/%c/%d(%5d): %s\n", |
| + idChar, priChar, etag, getpid(), prefixBuf); |
| + // log to syslog |
| + syslog(sys_pri, "%s", defaultBuf); |
| + ret = strlen(defaultBuf); |
| + } |
| + else |
| +#endif |
| + { /* radio, system, main */ |
| + // get messages and tag from io vector |
| + msg_len = vec[2].iov_len; |
| + priority = *((int *)vec[0].iov_base); |
| + tag = (char *)vec[1].iov_base; |
| + msg = (char *)vec[2].iov_base; |
| + |
| + /* disable Android VERBOSE log */ |
| + if (priority == ANDROID_LOG_VERBOSE) { |
| + return -EINVAL; |
| + } |
| + |
| + // get priority and logid char |
| + priChar = filterPriAndSysPri(priority, &sys_pri); |
| + |
| + // format prefix (brief format) |
| + prefixLen = snprintf(prefixBuf, sizeof(prefixBuf), |
| + "(%5d, %5d),[%s],[%d],[Tag]%s[TAG]: ", getpid(), syscall(SYS_gettid), idChar, priChar, tag); |
| + |
| + // compute size |
| + totalLen = prefixLen + msg_len + 1 + 1; |
| + if(totalLen <= defaultLen) { |
| + writeBuf = defaultBuf; |
| + } else { |
| + write_allocate = 1; |
| + writeBuf = (char *)malloc(totalLen); |
| + if(writeBuf == NULL) |
| + return 0; |
| + } |
| + |
| + // combine final string |
| + writeBuf[0] = '\0'; |
| + strncat(writeBuf, prefixBuf, prefixLen); |
| + strncat(writeBuf, msg, msg_len); |
| + strcat(writeBuf, "\n"); |
| + |
| + // log to syslog |
| + syslog(sys_pri, "%s", writeBuf); |
| + ret = strlen(writeBuf); |
| + |
| + if(write_allocate) free(writeBuf); |
| + } |
| +#else |
| struct android_log_transport_write *node; |
| int ret; |
| struct timespec ts; |
| @@ -316,6 +503,7 @@ static int __write_to_log_daemon(log_id_t log_id, struct iovec *vec, size_t nr) |
| (void)(*node->write)(log_id, &ts, vec, nr); |
| } |
| } |
| +#endif |
| |
| return ret; |
| } |
| @@ -327,6 +515,27 @@ static int __write_to_log_init(log_id_t log_id, struct iovec *vec, size_t nr) |
| if (write_to_log == __write_to_log_init) { |
| int ret; |
| |
| +#if defined(__REDIRECT_TO_SYSLOGD__) |
| + // open syslogd |
| + if (access("/etc/configs/syslog_split", F_OK) == 0) { |
| + switch (log_id) { |
| + case LOG_ID_MAIN: |
| + openlog("ALOG", 0, LOG_LOCAL0); |
| + break; |
| + case LOG_ID_SYSTEM: |
| + openlog("SLOG", 0, LOG_LOCAL1); |
| + break; |
| + case LOG_ID_RADIO: |
| + openlog("RLOG", 0, LOG_LOCAL2); |
| + break; |
| + default: |
| + openlog("ALOG", 0, LOG_LOCAL0); |
| + break; |
| + } |
| + } else { |
| + openlog("ALOG", 0, LOG_USER); |
| + } |
| +#else |
| ret = __write_to_log_initialize(); |
| if (ret < 0) { |
| __android_log_unlock(); |
| @@ -335,7 +544,7 @@ static int __write_to_log_init(log_id_t log_id, struct iovec *vec, size_t nr) |
| } |
| return ret; |
| } |
| - |
| +#endif |
| write_to_log = __write_to_log_daemon; |
| } |
| |