Add toolchain and mbtk source
Change-Id: Ie12546301367ea59240bf23d5e184ad7e36e40b3
diff --git a/mbtk/mbtk_logd/Makefile b/mbtk/mbtk_logd/Makefile
new file mode 100755
index 0000000..562a644
--- /dev/null
+++ b/mbtk/mbtk_logd/Makefile
@@ -0,0 +1,40 @@
+ROOT = $(shell pwd)/../..
+include ../Make.defines
+
+LOCAL_PATH=$(BUILD_ROOT)/mbtk_logd
+
+INC_DIR += -I$(BUILD_ROOT)
+
+LIB_DIR +=
+
+LIBS += -lubus -lubox -ljson-c -lblobmsg_json
+
+CFLAGS +=
+
+DEFINE +=
+
+MY_FILES_PATH:=$(LOCAL_PATH)
+#ifeq ($(CONFIG_MBTK_QL_SUPPORT),y)
+#MY_FILES_PATH += $(LOCAL_PATH)/ql
+#endif
+
+#ifeq ($(CONFIG_MBTK_PLATFORM),linux)
+#MY_FILES_PATH += $(LOCAL_PATH)/platform/linux
+#endif
+
+MY_FILES_SUFFIX:=%.c %.cpp
+My_All_Files := $(foreach src_path,$(MY_FILES_PATH), $(shell find "$(src_path)" -type f))
+MY_SRC_LIST := $(filter $(MY_FILES_SUFFIX),$(My_All_Files))
+MY_SRC_LIST := $(MY_SRC_LIST:$(LOCAL_PATH)/%=%)
+LOCAL_SRC_FILES += $(MY_SRC_LIST)
+$(info LOCAL_SRC_FILES = $(LOCAL_SRC_FILES))
+
+dtarget := $(OUT_DIR)/bin/mbtk_logd
+
+all: $(dtarget)
+
+$(dtarget):
+ $(CC) $(CFLAGS) $(LOCAL_SRC_FILES) -o $@ $(DEFINE) $(INC_DIR) $(LIB_DIR) $(LIBS)
+
+clean:
+
diff --git a/mbtk/mbtk_logd/alog_read.c b/mbtk/mbtk_logd/alog_read.c
new file mode 100755
index 0000000..33f227f
--- /dev/null
+++ b/mbtk/mbtk_logd/alog_read.c
@@ -0,0 +1,283 @@
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#include <fcntl.h>
+#include <time.h>
+#include <unistd.h>
+#include <errno.h>
+#include "log_config.h"
+
+#define ALOG_DEV "/dev/log_radio"
+
+typedef enum android_LogPriority {
+ ANDROID_LOG_UNKNOWN = 0,
+ ANDROID_LOG_DEFAULT, /* only for SetMinPriority() */
+ ANDROID_LOG_VERBOSE,
+ ANDROID_LOG_DEBUG,
+ ANDROID_LOG_INFO,
+ ANDROID_LOG_WARN,
+ ANDROID_LOG_ERROR,
+ ANDROID_LOG_FATAL,
+ ANDROID_LOG_SILENT, /* only for SetMinPriority(); must be last */
+} android_LogPriority;
+
+typedef struct AndroidLogEntry_t {
+ time_t tv_sec;
+ long tv_nsec;
+ android_LogPriority priority;
+ int32_t pid;
+ int32_t tid;
+ const char * tag;
+ size_t messageLen;
+ const char * message;
+} AndroidLogEntry;
+
+static const char *log_file, *log_ip, *log_port, *log_prefix, *pid_file, *hostname;
+static int log_size = 1 * 1024 * 1024;
+
+static log_config_entry *config = NULL;
+static char tmp_log[48] = {0};
+
+void hex_print(char* buf, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++) {
+ printf("%x ", buf[i]);
+ }
+}
+
+static char filterPriToChar(android_LogPriority pri)
+{
+ switch (pri) {
+ case ANDROID_LOG_VERBOSE:
+ return 'V';
+ case ANDROID_LOG_DEBUG:
+ return 'D';
+ case ANDROID_LOG_INFO:
+ return 'I';
+ case ANDROID_LOG_WARN:
+ return 'W';
+ case ANDROID_LOG_ERROR:
+ return 'E';
+ case ANDROID_LOG_FATAL:
+ return 'F';
+ case ANDROID_LOG_SILENT:
+ return 'S';
+
+ case ANDROID_LOG_DEFAULT:
+ case ANDROID_LOG_UNKNOWN:
+ default:
+ return '?';
+ }
+}
+
+static android_LogPriority filterCharToPri(char c)
+{
+ switch (c) {
+ case 'v':
+ return ANDROID_LOG_VERBOSE;
+ case 'd':
+ return ANDROID_LOG_DEBUG;
+ case 'i':
+ return ANDROID_LOG_INFO;
+ case 'w':
+ return ANDROID_LOG_WARN;
+ case 'e':
+ return ANDROID_LOG_ERROR;
+ case 'f':
+ return ANDROID_LOG_FATAL;
+ case 's':
+ return ANDROID_LOG_SILENT;
+ case '*':
+ default:
+ return ANDROID_LOG_VERBOSE;
+ }
+}
+
+int fileter_log(int pri, char *tag, struct filter_list_t *filter)
+{
+ struct filter_list_t *_filter = filter;
+
+ while(_filter)
+ {
+ int p = filterCharToPri(_filter->priority);
+ if(_filter->tag)
+ {
+ int len = strlen(_filter->tag);
+ // tag and priority
+ if(0 == memcmp(_filter->tag, tag, len) && ((pri > p) || (pri == p)))
+ return 0;
+ }else{ // have no tag
+ if(pri < p)
+ return -1;
+ else
+ return 0;
+ }
+ _filter = _filter->next;
+ }
+
+ return -1;
+}
+
+int alog_process(char* data, int len, AndroidLogEntry *entry)
+{
+ int i, n = 0;
+ int tmp_len;
+
+ for (i = 0; i < len;) {
+ if (data[i] == '\0') {
+ i += 1;
+ } else {
+ switch (n) {
+ case 0: {
+ // printf("%d - %d: %x\n", i, tmp_len, data[i]);
+ i++;
+ break;
+ }
+ case 1: {
+ int* pid = (int*)&data[i];
+ entry->pid = *pid;
+ // printf("%d pid: %d\n", i, entry->pid);
+ i += 4;
+ break;
+ }
+ case 2: {
+ int* tid = (int*)&data[i];
+ entry->tid = *tid;
+ // printf("%d tid: %d\n", i, entry->tid);
+ i += 4;
+ break;
+ }
+ case 3: {
+ // printf("%d - %d: %x %x %x %x\n", i, tmp_len, data[i], data[i + 1], data[i + 2], data[i + 3]);
+ time_t* _t = (time_t*)&data[i];
+ entry->tv_sec = *_t;
+ i += 8;
+ break;
+ }
+ case 4: {
+ entry->priority = data[i];
+ entry->tag = &data[i + 1];
+ i += strlen(&data[i]);
+ break;
+ }
+ //* format: <priority:1><tag:N>\0<message:N>\0
+ case 5: {
+ entry->message = &data[i];
+ entry->messageLen = strlen(&data[i]);
+ i += entry->messageLen;
+ break;
+ }
+ default:
+ printf("process error \n");
+ break;
+ }
+ n++;
+ }
+ }
+ return 0;
+}
+
+int android_log_printLogLine(
+ int fd,
+ struct file_list_t *_file_list,
+ const AndroidLogEntry *entry)
+{
+ char priChar;
+ char timeBuf[32];
+ char defaultBuffer[512];
+ size_t totalLen;
+ int fd_new = fd;
+ struct stat s;
+ char * ret = NULL;
+
+ if (log_size && (!stat(tmp_log, &s)) && (s.st_size > log_size)) {
+ fd_new = get_rotate_file(fd_new, log_file, _file_list);
+ if (fd_new < 0) {
+ fprintf(stderr, "failed to open %s: %s\n", log_file, strerror(errno));
+ exit(-1);
+ }
+ }
+
+ if(fileter_log(entry->priority, entry->tag, config->filter_list))
+ {
+ // printf("%s %d: fileter pri:%d tag:%s!\n", __FUNCTION__, __LINE__, entry->priority, entry->tag);
+ return -1;
+ }
+
+ priChar = filterPriToChar(entry->priority);
+ struct tm* ptm = localtime(&entry->tv_sec);
+ strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M:%S", ptm);
+
+ totalLen = snprintf(defaultBuffer, sizeof(defaultBuffer),
+ "%s %c/%s (%d): %s\n", timeBuf, priChar, entry->tag, entry->pid, entry->message);
+
+ ret = write(fd_new, defaultBuffer, totalLen);
+
+ return ret;
+}
+
+void* alog_thread(void* argv)
+{
+ int dev_fd, ret;
+ int log_fd;
+ AndroidLogEntry entry;
+ char buf[512] = {0};
+ static struct file_list_t file_list;
+ config = (log_config_entry *)argv;
+
+ pthread_detach(pthread_self());
+ if (NULL == argv)
+ return NULL;
+
+ dev_fd = open(ALOG_DEV, O_RDONLY, 0600);
+ if (dev_fd < 0) {
+ fprintf(stderr, "failed to open %s: %s\n", ALOG_DEV, strerror(errno));
+ exit(-1);
+ }
+
+ memset(&file_list, 0, sizeof(struct file_list_t));
+ file_list.total = config->rotate_file_count;
+ log_file = config->out_path;
+
+ if (config->ip && config->port) {
+ int port = atoi(config->port);
+ printf("%s %d : %s:%s\n", __FUNCTION__, __LINE__, config->ip, config->port);
+ log_fd = tcp_connect(config->ip, port);
+ } else if (log_file) {
+ sprintf(tmp_log, "/tmp/log%s", strstr_tail(log_file, "/"));
+ // 先将文件保存到 /tmp/log/ 目录下,后面到达 rotate_file_size 后,转移到out_path
+ log_fd = open(tmp_log, O_CREAT | O_WRONLY| O_APPEND, 0600);
+ if (log_fd < 0) {
+ fprintf(stderr, "failed to open %s: %s\n", tmp_log, strerror(errno));
+ exit(-1);
+ }
+ } else {
+ log_fd = STDOUT_FILENO;
+ }
+ if(config->rotate_file_size)
+ log_size = config->rotate_file_size;
+
+ printf("android log start...\n");
+ while (1) {
+ ret = read(dev_fd, buf, sizeof(buf));
+ if (ret < 0) {
+ printf("read error\n");
+ break;
+ }
+ alog_process(buf, ret, &entry);
+ android_log_printLogLine(log_fd, &file_list, &entry);
+ memset(buf, 0, sizeof(buf));
+ }
+ close(dev_fd);
+ close(log_fd);
+
+ printf("%s exit \n", __FUNCTION__);
+ pthread_exit(NULL);
+ return NULL;
+}
diff --git a/mbtk/mbtk_logd/common.c b/mbtk/mbtk_logd/common.c
new file mode 100755
index 0000000..1e293b6
--- /dev/null
+++ b/mbtk/mbtk_logd/common.c
@@ -0,0 +1,282 @@
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <fcntl.h>
+#include <time.h>
+#include <unistd.h>
+#include <time.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dirent.h>
+#include "log_config.h"
+
+/* 文件大小和修改时间 */
+static int get_file_size_time(const char *filename)
+{
+ struct stat statbuf;
+ /* 判断未打开文件 */
+ if(stat(filename,&statbuf)==-1)
+ {
+ printf("Get stat on %s Error: %s\n", filename, strerror(errno));
+ return(-1);
+ }
+ if(S_ISDIR(statbuf.st_mode)) // 目录
+ return(1);
+ if(S_ISREG(statbuf.st_mode)) // 文件
+ printf("%s size: %ld bytes\tmodified at %s", filename, statbuf.st_size, ctime(&statbuf.st_mtime));
+ return(0);
+}
+
+int __main(int argc,char **argv)
+{
+ DIR *dirp;
+ struct dirent *direntp;
+ int stats;
+
+ if(argc!=2)
+ {
+ printf("Usage: %s filename\n\a", argv[0]);
+ exit(1);
+ }
+
+ if(((stats=get_file_size_time(argv[1]))==0)||(stats==-1)) // 文件或出现错误
+ exit(1);
+
+ /* 打开目录 */
+ if((dirp=opendir(argv[1]))==NULL)
+ {
+ printf("Open Directory %s Error: %s\n", argv[1], strerror(errno));
+ exit(1);
+ }
+
+ /* 返回目录中文件大小和修改时间 */
+ while((direntp=readdir(dirp))!=NULL)
+ {
+ /* 给文件或目录名添加路径:argv[1]+"/"+direntp->d_name */
+ char dirbuf[512];
+ memset(dirbuf,0,sizeof(dirbuf));
+ strcpy(dirbuf,argv[1]);
+ strcat(dirbuf,"/");
+ strcat(dirbuf,direntp->d_name);
+ if(get_file_size_time(dirbuf)==-1) break;
+ }
+
+ closedir(dirp);
+ exit(1);
+}
+// 从后往前找
+char *strstr_tail(const char *dst, const char *src)
+{
+ if(NULL == dst || NULL == src)
+ return NULL;
+ const char *pdst = dst;
+ const char *psrc = src;
+ char *tmp = NULL ;
+ while (*pdst) //因为要从后向前找,则首先让pdst指向'\0'
+ {
+ pdst++;
+ }
+
+ while (pdst >= dst ) //当pdst大于dst则表明dst这个字符串还没有找完
+ {
+ if (tmp=(char *)strstr(pdst, psrc = src)) //使用strstr帮助寻找,找到保存到tmp
+ return tmp;
+
+ pdst--;
+ }
+
+ return NULL ;
+}
+
+char* strcpy_malloc(char* src)
+{
+ if (NULL == src || 0 == strlen(src)) {
+ return NULL;
+ }
+ int len = strlen(src);
+ char* temp = malloc(len + 1);
+ if (NULL == temp) {
+ return NULL;
+ }
+ memset(temp, 0, len + 1);
+ strcpy(temp, src);
+
+ return temp;
+}
+
+int get_time (char *out_time)
+{
+ time_t rawtime;
+ struct tm *info;
+ char buffer[16] = {0};
+
+ time( &rawtime );
+ info = localtime(&rawtime);
+ strftime(buffer, sizeof(buffer), "%Y%m%d%H%M%S \n", info);
+ if(out_time)
+ memcpy(out_time, &buffer[2], 12);
+
+ return(0);
+}
+
+int tcp_connect(char* ip, int port)
+{
+ int sockfd;
+ struct hostent* he;
+ struct sockaddr_in server;
+
+ he = gethostbyname(ip);
+
+ if (he == NULL) {
+ printf("gethostbyname error\n");
+ exit(1);
+ }
+
+ sockfd = socket(AF_INET, SOCK_STREAM, 0);
+
+ if (sockfd == -1) {
+ printf("socket error\n");
+ exit(1);
+ }
+
+ bzero(&server, sizeof(server));
+ server.sin_family = AF_INET;
+ server.sin_port = htons(port);
+ server.sin_addr = *((struct in_addr*)he->h_addr);
+
+ if (connect(sockfd, (struct sockaddr*)&server, sizeof(server)) == -1) {
+ printf("connect error\n");
+ exit(1);
+ }
+
+ return sockfd;
+}
+int movefile(char *src, char *dst)
+{
+ if (strcmp(src, dst) == 0)
+ {
+ printf("Destination file name and source file name can't be the same!");
+ return -1;
+ }
+ FILE *fsrc = fopen(src, "rb"); //一定要“rb”否则复制的文件有时会不能使用
+ FILE *fdst = fopen(dst, "wb"); //一定要“wb”否则复制的文件有时会不能使用
+ int buflen = 1024;
+ char buf[1024];
+ int nread = 0;
+ while ((nread = fread(buf, 1, buflen, fsrc)) > 0) //最好把读文件的代码放这里
+ {
+ fwrite(buf, 1, nread, fdst);
+ }
+
+ fclose(fsrc);
+ fsrc = NULL;
+ fclose(fdst);
+ fdst = NULL;
+ remove(src);//删除源文件
+
+ return 0;
+}
+/**
+ * @brief get_rotate_file
+ *
+ * @details 转移log文件
+ *
+ * @param param
+ *
+ * @return return type
+ */
+int get_rotate_file(int fd, char *base_file, struct file_list_t *_file_list)
+{
+ char _time[16] = {0};
+ int num = 0;
+ char tmp_buf[48] = {0};
+ char *current_file = _file_list->file[_file_list->current];
+ int len = strlen(base_file);
+ char *old = malloc(len + 20);
+ int rotate_file_count_max;
+
+ if(_file_list->total == -1 || _file_list->total == 0 || _file_list->total > ROTATE_FILE_COUNT_MAX)
+ rotate_file_count_max = ROTATE_FILE_COUNT_MAX;
+ else
+ rotate_file_count_max = _file_list->total;
+
+
+ if(0 == _file_list->current && NULL == current_file)
+ _file_list->current = rotate_file_count_max - 1;
+ if(NULL == old)
+ {
+ fprintf(stderr, "failed to malloc %s\n", strerror(errno));
+ exit(-1);
+ }
+ close(fd);
+ sprintf(tmp_buf, "/tmp/log%s", strstr_tail(base_file, "/"));
+ get_time(_time);
+ sprintf(old, "%s.%s", base_file, _time);
+ if (current_file && strstr(current_file, old)) {
+ int tmp_len = strlen(current_file);
+ // 以时间命名的文件是否已经存在
+ if(current_file[tmp_len - 3] == '.'){
+ num = atoi(¤t_file[tmp_len - 2]);
+ num++;
+ sprintf(old, "%s.%02d", old, num);
+ }else{
+ sprintf(old, "%s.%02d", old, num);
+ }
+ }
+ if (movefile(tmp_buf, old) != 0){
+ printf("%s %d: Renamed error ,%s to %s.\n", __FUNCTION__, __LINE__, tmp_buf, old);
+ }
+ _file_list->current++;
+ // ringbuf
+ if(_file_list->current > (rotate_file_count_max - 1))
+ {
+ _file_list->current = 0;
+ }
+ // 如果之前已经存在,先释放之前存放的资源
+ if(_file_list->file[_file_list->current])
+ {
+ // printf("%s %d: remove %s\n", __FUNCTION__, __LINE__, _file_list->file[_file_list->current]);
+ // 如果 不限制文件数目,则不删除文件
+ if(_file_list->total != -1)
+ unlink(_file_list->file[_file_list->current]);
+ free(_file_list->file[_file_list->current]);
+ }
+ // 将文件名保存下来
+ _file_list->file[_file_list->current] = strdup(old);
+ free(old);
+ int fd_new = open(tmp_buf, O_CREAT | O_WRONLY | O_APPEND, 0600);
+ if (fd_new < 0) {
+ fprintf(stderr, "failed to open %s: %s\n", tmp_buf, strerror(errno));
+ exit(-1);
+ }
+
+ return fd_new;
+}
+
+#if 0
+void get_rotate_file_test()
+{
+ struct file_list_t file_list;
+ int i;
+ char *test_path = "/tmp/log/m_log.txt";
+
+ memset(&file_list, 0, sizeof(struct file_list_t));
+ file_list.total = 3;
+
+ int fd = open(test_path, O_CREAT | O_WRONLY | O_APPEND, 0600);
+ if (fd < 0) {
+ fprintf(stderr, "failed to open %s: %s\n", test_path, strerror(errno));
+ exit(-1);
+ }
+ write(fd, "test1111", 8);
+ for (i = 0; i < 6; ++i) {
+ // sleep(1);
+ fd = get_rotate_file(fd, test_path, &file_list);
+ write(fd, "test2222", 8);
+ }
+ close(fd);
+}
+#endif
diff --git a/mbtk/mbtk_logd/common_read.c b/mbtk/mbtk_logd/common_read.c
new file mode 100755
index 0000000..90f2f7f
--- /dev/null
+++ b/mbtk/mbtk_logd/common_read.c
@@ -0,0 +1,146 @@
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#include <fcntl.h>
+#include <time.h>
+#include <unistd.h>
+#include <errno.h>
+#include "log_config.h"
+
+#define ALOG_DEV "/dev/log_radio"
+
+static const char *log_file, *log_ip, *log_port, *log_prefix, *pid_file, *hostname;
+static int log_size = 1 * 1024 * 1024;
+
+static log_config_entry *config = NULL;
+static char tmp_log[48] = {0};
+
+
+static int fileter_log(int pri, char *tag, struct filter_list_t *filter)
+{
+ struct filter_list_t *_filter = filter;
+
+ while(_filter)
+ {
+ // _filter->priority
+ // 获取 筛选的等级 p
+ int p = 0;
+ if(_filter->tag)
+ {
+ int len = strlen(_filter->tag);
+ // tag and priority
+ if(0 == memcmp(_filter->tag, tag, len) && ((pri > p) || (pri == p)))
+ return 0;
+ }else{ // have no tag
+ if(pri < p)
+ return -1;
+ else
+ return 0;
+ }
+ _filter = _filter->next;
+ }
+
+ return -1;
+}
+
+int common_log_print(
+ int fd,
+ struct file_list_t *_file_list,
+ char *entry)
+{
+ char priChar;
+ char timeBuf[32];
+ char defaultBuffer[512];
+ size_t totalLen;
+ int fd_new = fd;
+ struct stat s;
+ time_t timetemp; // 定义一个时间结构体变量
+ char * ret = NULL;
+
+ if (log_size && (!stat(tmp_log, &s)) && (s.st_size > log_size)) {
+ fd_new = get_rotate_file(fd_new, log_file, _file_list);
+ if (fd_new < 0) {
+ fprintf(stderr, "failed to open %s: %s\n", log_file, strerror(errno));
+ exit(-1);
+ }
+ }
+
+ // if(fileter_log(entry->priority, entry->tag, config->filter_list))
+ // {
+ // printf("%s %d: fileter pri:%d tag:%s!\n", __FUNCTION__, __LINE__, entry->priority, entry->tag);
+ // return -1;
+ // }
+ time(&timetemp); // 获得时间参数
+ struct tm* ptm = localtime(&timetemp);
+ strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M:%S", ptm);
+
+ totalLen = snprintf(defaultBuffer, sizeof(defaultBuffer),
+ "%s : %s\n", timeBuf, entry);
+
+ ret = write(fd_new, defaultBuffer, totalLen);
+
+ return ret;
+}
+
+void* common_log_thread(void* argv)
+{
+ int dev_fd, ret;
+ int log_fd;
+ char buf[512] = {0};
+ static struct file_list_t file_list;
+ config = (log_config_entry *)argv;
+
+ pthread_detach(pthread_self());
+ if (NULL == argv || NULL == config->name)
+ return NULL;
+
+ dev_fd = open(config->name, O_RDONLY, 0600);
+ if (dev_fd < 0) {
+ fprintf(stderr, "failed to open %s: %s\n", config->name, strerror(errno));
+ exit(-1);
+ }
+
+ memset(&file_list, 0, sizeof(struct file_list_t));
+ file_list.total = config->rotate_file_count;
+ log_file = config->out_path;
+
+ if (config->ip && config->port) {
+ int port = atoi(config->port);
+ printf("%s %d : %s:%s\n", __FUNCTION__, __LINE__, config->ip, config->port);
+ log_fd = tcp_connect(config->ip, port);
+ } else if (log_file) {
+ sprintf(tmp_log, "/tmp/log%s", strstr_tail(log_file, "/"));
+ // 先将文件保存到 /tmp/log/ 目录下,后面到达 rotate_file_size 后,转移到out_path
+ log_fd = open(tmp_log, O_CREAT | O_WRONLY| O_APPEND, 0600);
+ if (log_fd < 0) {
+ fprintf(stderr, "failed to open %s: %s\n", tmp_log, strerror(errno));
+ exit(-1);
+ }
+ } else {
+ log_fd = STDOUT_FILENO;
+ }
+ if(config->rotate_file_size)
+ log_size = config->rotate_file_size;
+
+ printf("uart log start...\n");
+ while (1) {
+ ret = read(dev_fd, buf, sizeof(buf));
+ if (ret < 0) {
+ printf("read error\n");
+ break;
+ }
+ // common_log_process(buf, ret, &entry);
+ common_log_print(log_fd, &file_list, buf);
+ memset(buf, 0, sizeof(buf));
+ }
+ close(dev_fd);
+ close(log_fd);
+
+ printf("%s exit \n", __FUNCTION__);
+ pthread_exit(NULL);
+ return NULL;
+}
diff --git a/mbtk/mbtk_logd/log_config.h b/mbtk/mbtk_logd/log_config.h
new file mode 100755
index 0000000..c37ce24
--- /dev/null
+++ b/mbtk/mbtk_logd/log_config.h
@@ -0,0 +1,41 @@
+#ifndef _LOG_CONFIG_H
+#define _LOG_CONFIG_H
+
+
+#define LOG_CONFIG_PATH "/etc/mbtk/mbtk_log.json"
+
+#define ROTATE_FILE_COUNT_MAX 10
+
+struct filter_list_t {
+ char priority;
+ char *tag;
+ struct filter_list_t *next;
+};
+
+struct file_list_t {
+ int total;
+ int current;
+ char *base_file;
+ char *file[ROTATE_FILE_COUNT_MAX];
+};
+
+typedef struct log_config_entry_t {
+ int enable;
+ char *name;
+ int send_fd;
+ char *out_path;
+ char *ip;
+ char *port;
+ int rotate_file_size;
+ int rotate_file_count;
+ int32_t log_format;
+ struct filter_list_t *filter_list;
+} log_config_entry;
+
+int get_rotate_file(int fd, char *base_file, struct file_list_t *_file_list);
+extern void* alog_thread(void* argv);
+extern void* syslog_main(void* argv);
+extern void* socket_log_thread(void* argv);
+extern void* common_log_thread(void* argv);
+
+#endif // _LOG_CONFIG_H
diff --git a/mbtk/mbtk_logd/main.c b/mbtk/mbtk_logd/main.c
new file mode 100755
index 0000000..25dbdb1
--- /dev/null
+++ b/mbtk/mbtk_logd/main.c
@@ -0,0 +1,283 @@
+#include <stdio.h>
+#include <fcntl.h>
+#include <time.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <time.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "json/json.h"
+#include "json/printbuf.h"
+#include "log_config.h"
+
+// #define DEBUG 1
+
+#ifdef DEBUG
+#define mbtk_log(...) printf(__VA_ARGS__)
+#else
+#define mbtk_log(...)
+#endif
+
+static void handler_free(log_config_entry* listdata)
+{
+ int i, n;
+ struct filter_list_t* _filter_list = NULL;
+ log_config_entry* entry;
+
+ for (i = 0; i < 5; i++) {
+ entry = listdata + i;
+ if (entry->name) {
+ free(entry->name);
+ if (entry->out_path) {
+ free(entry->out_path);
+ }
+ if (entry->ip) {
+ free(entry->ip);
+ }
+ _filter_list = entry->filter_list;
+ for (n = 0; n < 10; n++) {
+ printf("%s %d: malloc %x!\n", __FUNCTION__, __LINE__, _filter_list);
+ if (_filter_list) {
+ printf("%s %d: malloc %x!\n", __FUNCTION__, __LINE__, _filter_list->next);
+ if (_filter_list->tag) {
+ free(_filter_list->tag);
+ }
+ free(_filter_list);
+ _filter_list = _filter_list->next;
+ } else {
+ break;
+ }
+ }
+ } else {
+ break;
+ }
+ }
+}
+
+int parse_config(log_config_entry* listdata)
+{
+ json_object* jsonobj = NULL;
+ json_object* tmpjson = NULL;
+ json_object* datajson = NULL;
+ json_object* listjson = NULL;
+ json_object* fileterjson = NULL;
+ json_object* fileter_listjson = NULL;
+ log_config_entry* entry;
+ int i, n, ret;
+ char* cmdval = NULL;
+
+ jsonobj = json_object_from_file(LOG_CONFIG_PATH);
+ if (NULL == jsonobj) {
+ printf("Can't open config file: %s\n", LOG_CONFIG_PATH);
+ return -1;
+ }
+ ret = json_object_object_get_ex(jsonobj, "logd", &tmpjson);
+ if (!ret) {
+ printf("get jsondata error ...\n");
+ }
+
+ if (NULL == tmpjson) {
+ printf("the tmpjson : [%s]\n", json_object_to_json_string(tmpjson));
+ }
+ /**获取total***/
+ cmdval = json_object_get_string(tmpjson);
+ printf("logd enable : %s\n", cmdval);
+ json_object_put(tmpjson);
+ /***获取data***/
+ json_object_object_get_ex(jsonobj, "buffer_list", &tmpjson);
+ for (i = 0 ; i < 5; i++) {
+ struct filter_list_t* _filter_list = NULL;
+ struct filter_list_t* tmp_filter_list = NULL;
+ datajson = json_object_array_get_idx(tmpjson, i);
+ if (NULL == datajson) {
+ mbtk_log("the datajson exit\n");
+ break;
+ }
+ entry = listdata + i;
+ json_object_object_get_ex(datajson, "enable", &listjson);
+ entry->enable = json_object_get_int(listjson);
+ mbtk_log("enable: %d\n", entry->enable);
+
+ json_object_object_get_ex(datajson, "name", &listjson);
+ entry->name = strdup(json_object_get_string(listjson));
+ mbtk_log("cmdval: %x, %s\n", entry->name, entry->name);
+
+ json_object_object_get_ex(datajson, "log_file", &listjson);
+ entry->out_path = strdup(json_object_get_string(listjson));
+ mbtk_log("cmdval: %s\n", entry->out_path);
+
+ json_object_object_get_ex(datajson, "log_stream", &listjson);
+ if (listjson) {
+ entry->ip = strdup(json_object_get_string(listjson));
+ cmdval = strstr(entry->ip, ":");
+ if (cmdval) {
+ entry->port = &cmdval[1];
+ cmdval[0] = 0;
+ mbtk_log("cmdval: %s [%s]\n", entry->ip, entry->port);
+ } else {
+ printf("Can't find port!!\n");
+ free(entry->ip);
+ entry->ip = NULL;
+ }
+ }
+ json_object_object_get_ex(datajson, "rotate_file_size", &listjson);
+ entry->rotate_file_size = json_object_get_int(listjson) * 1024;
+ mbtk_log("rotate_file_size: %d\n", entry->rotate_file_size);
+
+ json_object_object_get_ex(datajson, "rotate_file_count", &listjson);
+ entry->rotate_file_count = json_object_get_int(listjson);
+ mbtk_log("rotate_file_count: %d\n", entry->rotate_file_count);
+
+ json_object_object_get_ex(datajson, "filter_list", &listjson);
+ if (NULL == listjson) {
+ printf("%s %d: object failure!\n", __FUNCTION__, __LINE__);
+ json_object_put(listjson);
+ continue;
+ }
+ entry->filter_list = (struct filter_list_t*)malloc(sizeof(struct filter_list_t));
+ _filter_list = entry->filter_list;
+
+ for (n = 0 ; n < 5; n++) {
+ fileterjson = json_object_array_get_idx(listjson, n);
+ if (NULL == fileterjson) {
+ mbtk_log("the fileterjson exit\n");
+ free(tmp_filter_list->next);
+ tmp_filter_list->next = NULL;
+ break;
+ }
+ memset(_filter_list, 0, sizeof(struct filter_list_t));
+ json_object_object_get_ex(fileterjson, "priority", &fileter_listjson);
+ char* str = json_object_get_string(fileter_listjson);
+ if (str) {
+ _filter_list->priority = str[0];
+ mbtk_log("fileter_listjson: %c\n", _filter_list->priority);
+ }
+ json_object_object_get_ex(fileterjson, "tag", &fileter_listjson);
+ // if (NULL == fileter_listjson) {
+ // printf("%s %d: object failure!\n", __FUNCTION__, __LINE__);
+ // }
+ str = json_object_get_string(fileter_listjson);
+ if (str) {
+ _filter_list->tag = strdup(str);
+ mbtk_log("fileter_listjson: %s\n", _filter_list->tag);
+ }
+ json_object_put(fileter_listjson);
+ _filter_list->next = (struct filter_list_t*)malloc(sizeof(struct filter_list_t));
+ if (NULL == _filter_list->next) {
+ printf("%s %d: malloc failure!\n", __FUNCTION__, __LINE__);
+ break;
+ }
+ tmp_filter_list = _filter_list;
+ _filter_list = _filter_list->next;
+ }
+ json_object_put(listjson);
+ }
+ json_object_put(tmpjson);
+
+ /***释放json对象***/
+ json_object_put(jsonobj);
+
+ return 0;
+}
+
+#define LOGD_PID "/var/run/mbtk_logd.pid"
+
+static int save_pid(void)
+{
+ pid_t process_id;
+ int fd, ret;
+ char buf[12] = {0};
+
+ process_id = getpid();
+ if(access(LOGD_PID, F_OK) == 0)
+ {
+ printf("mbtk_logd 进程已经存在\n");
+ return -1;
+ }
+ fd = open(LOGD_PID, O_CREAT | O_WRONLY, 0600);
+ if (fd < 0) {
+ fprintf(stderr, "failed to open %s: %s\n", LOGD_PID, strerror(errno));
+ return -2;
+ }
+ snprintf(buf, sizeof(buf), "%d\n", process_id);
+ ret = write(fd, buf, strlen(buf));
+ close(fd);
+
+ if(ret > 0)
+ return 0;
+ else
+ return -2;
+}
+
+int main(int argc, char* argv[])
+{
+ log_config_entry listdata[5];
+ pthread_t pid[5] = {0};
+ int i, ret;
+ void* tret;
+
+ memset(listdata, 0, sizeof(log_config_entry) * 5);
+
+ ret = parse_config(listdata);
+ if (ret) {
+ return -1;
+ }
+ if(0 != save_pid())
+ {
+ printf("%s %d: logd exit!\n", __FUNCTION__, __LINE__);
+ return -1;
+ }
+
+ printf("logd %s start !\n", __FUNCTION__);
+
+ for (i = 0; i < 5; ++i) {
+ if (NULL == listdata[i].name) {
+ break;
+ }
+
+ if (0 == listdata[i].enable) {
+ printf("%s log disabled !\n", listdata[i].name);
+ continue;
+ }
+
+ if (0 == memcmp(listdata[i].name, "radio", 5)) {
+ ret = pthread_create(&pid[i], NULL, alog_thread, &listdata[i]);
+ if (ret != 0) {
+ fprintf(stderr, "\n%s: Failed to create pthread\n", __FUNCTION__);
+ }
+ } else if (0 == memcmp(listdata[i].name, "syslog", 6)) {
+ ret = pthread_create(&pid[i], NULL, syslog_main, &listdata[i]);
+ if (ret != 0) {
+ fprintf(stderr, "\n%s %d: Failed to create pthread\n", __FUNCTION__, __LINE__);
+ }
+ } else if (0 == memcmp(listdata[i].name, "local_socket", 12)) {
+ ret = pthread_create(&pid[i], NULL, socket_log_thread, &listdata[i]);
+ if (ret != 0) {
+ fprintf(stderr, "\n%s %d: Failed to create pthread\n", __FUNCTION__, __LINE__);
+ }
+ } else if (0 == memcmp(listdata[i].name, "/dev/tty", 8)) {
+ ret = pthread_create(&pid[i], NULL, common_log_thread, &listdata[i]);
+ if (ret != 0) {
+ fprintf(stderr, "\n%s %d: Failed to create pthread\n", __FUNCTION__, __LINE__);
+ }
+ }
+ }
+
+ for (i = 0; i < 5; ++i) {
+ if (NULL == listdata[i].name) {
+ break;
+ }
+ if (pid[i]) {
+ if (pthread_join(pid[i], &tret) != 0) {
+ printf("Join thread %d : %d error!\n", i, pid[i]);
+ exit(1);
+ }
+ }
+ }
+ handler_free(listdata);
+
+ return 0;
+}
diff --git a/mbtk/mbtk_logd/socket_read.c b/mbtk/mbtk_logd/socket_read.c
new file mode 100755
index 0000000..df8fe27
--- /dev/null
+++ b/mbtk/mbtk_logd/socket_read.c
@@ -0,0 +1,228 @@
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#include <fcntl.h>
+#include <time.h>
+#include <unistd.h>
+#include <errno.h>
+#include "log_config.h"
+
+#define _MOPEN_RILD_CONNET_NUM 5
+#define _MOPEN_RILD_SOCKET "/tmp/logd_socket"
+
+static int client_sockfd[_MOPEN_RILD_CONNET_NUM];
+
+static const char* log_file, *log_ip, *log_port, *log_prefix, *pid_file, *hostname;
+static int log_size = 1 * 1024 * 1024;
+
+static log_config_entry* config = NULL;
+static char tmp_log[48] = {0};
+
+static int fileter_log(int pri, char* tag, struct filter_list_t* filter)
+{
+ struct filter_list_t* _filter = filter;
+
+ while (_filter) {
+ // _filter->priority
+ // 获取 筛选的等级 p
+ int p = 0;
+ if (_filter->tag) {
+ int len = strlen(_filter->tag);
+ // tag and priority
+ if (0 == memcmp(_filter->tag, tag, len) && ((pri > p) || (pri == p))) {
+ return 0;
+ }
+ } else { // have no tag
+ if (pri < p) {
+ return -1;
+ } else {
+ return 0;
+ }
+ }
+ _filter = _filter->next;
+ }
+
+ return -1;
+}
+
+int socket_log_print(
+ int fd,
+ struct file_list_t* _file_list,
+ char* entry)
+{
+ char priChar;
+ // char timeBuf[32];
+ // time_t timetemp; // 定义一个时间结构体变量
+ char defaultBuffer[512];
+ size_t totalLen;
+ int fd_new = fd;
+ struct stat s;
+ char* ret = NULL;
+
+ if (log_size && (!stat(tmp_log, &s)) && (s.st_size > log_size)) {
+ fd_new = get_rotate_file(fd_new, log_file, _file_list);
+ if (fd_new < 0) {
+ fprintf(stderr, "failed to open %s: %s\n", log_file, strerror(errno));
+ exit(-1);
+ }
+ }
+
+ // if(fileter_log(entry->priority, entry->tag, config->filter_list))
+ // {
+ // printf("%s %d: fileter pri:%d tag:%s!\n", __FUNCTION__, __LINE__, entry->priority, entry->tag);
+ // return -1;
+ // }
+ // time(&timetemp); // 获得时间参数
+ // struct tm* ptm = localtime(&timetemp);
+ // strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M:%S", ptm);
+ totalLen = snprintf(defaultBuffer, sizeof(defaultBuffer), "%s", entry);
+
+ ret = write(fd_new, defaultBuffer, totalLen);
+
+ return ret;
+}
+
+static int open_local_socket(char *path)
+{
+ int listen_fd;
+ int ret;
+ struct sockaddr_un srv_addr;
+
+ listen_fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (listen_fd < 0) {
+ printf("connect creat communication socket");
+ return -1;
+ }
+
+ unlink(path);
+ srv_addr.sun_family = AF_UNIX;
+ strcpy(srv_addr.sun_path, path);
+
+ ret = bind(listen_fd, (struct sockaddr*)&srv_addr, sizeof(srv_addr));
+ if (ret < 0) {
+ printf("cannot bind server socket");
+ close(listen_fd);
+ unlink(path);
+ return -1;
+ }
+
+ return listen_fd;
+}
+
+void* socket_log_thread(void* argv)
+{
+ int listen_fd;
+ int com_fd, fd_max, fd_num;
+ int ret, log_fd;
+ int i, n, str_len;
+ fd_set reads, cpy_reads;
+ struct timeval timeout;
+ char buf[512] = {0};
+ static struct file_list_t file_list;
+ config = (log_config_entry*)argv;
+
+ pthread_detach(pthread_self());
+ if (NULL == argv || NULL == config->name) {
+ return NULL;
+ }
+
+ memset(&file_list, 0, sizeof(struct file_list_t));
+ file_list.total = config->rotate_file_count;
+ log_file = config->out_path;
+
+ if (config->ip && config->port) {
+ int port = atoi(config->port);
+ printf("%s %d : %s:%s\n", __FUNCTION__, __LINE__, config->ip, config->port);
+ log_fd = tcp_connect(config->ip, port);
+ } else if (log_file) {
+ sprintf(tmp_log, "/tmp/log%s", strstr_tail(log_file, "/"));
+ // 先将文件保存到 /tmp/log/ 目录下,后面到达 rotate_file_size 后,转移到out_path
+ log_fd = open(tmp_log, O_CREAT | O_WRONLY | O_APPEND, 0600);
+ if (log_fd < 0) {
+ fprintf(stderr, "failed to open %s: %s\n", tmp_log, strerror(errno));
+ exit(-1);
+ }
+ } else {
+ log_fd = STDOUT_FILENO;
+ }
+ if (config->rotate_file_size) {
+ log_size = config->rotate_file_size;
+ }
+
+ listen_fd = open_local_socket(_MOPEN_RILD_SOCKET);
+ if (listen_fd < 0 || listen_fd == 0) {
+ return NULL;
+ }
+ ret = listen(listen_fd, 1);
+ if (ret < 0) {
+ printf("cannot listen sockfd");
+ close(listen_fd);
+ unlink(_MOPEN_RILD_SOCKET);
+ return NULL;
+ }
+ FD_ZERO(&reads);
+ FD_SET(listen_fd, &reads);
+ fd_max = listen_fd;
+ printf("socket log start...\n");
+ memset(client_sockfd, 0, sizeof(client_sockfd));
+ for (;;) {
+ cpy_reads = reads;
+ timeout.tv_sec = 5;
+ timeout.tv_usec = 5000;
+
+ if ((fd_num = select(fd_max + 1, &cpy_reads, 0, 0, &timeout)) == -1) {
+ perror("select error");
+ break;
+ }
+ if (fd_num == 0) {
+ continue;
+ }
+
+ for (n = 0; n < fd_max + 1; n++) {
+ if (FD_ISSET(n, &cpy_reads)) {
+ if (n == listen_fd) {
+ com_fd = accept(listen_fd, NULL, NULL);
+ FD_SET(com_fd, &reads);
+ if (fd_max < com_fd) {
+ fd_max = com_fd;
+ }
+ printf("accept accept fd [%d]", com_fd);
+ for (i = 0; i < _MOPEN_RILD_CONNET_NUM; i++) {
+ if (client_sockfd[i] <= 0) {
+ client_sockfd[i] = com_fd;
+ break;
+ }
+ }
+ } else {
+ str_len = read(n, buf, sizeof(buf));
+ if (str_len == 0) {
+ for (i = 0; i < _MOPEN_RILD_CONNET_NUM; i++) {
+ if (client_sockfd[i] == n) {
+ client_sockfd[i] = 0;
+ break;
+ }
+ }
+ FD_CLR(n, &reads);
+ close(n);
+ printf("closed client: %d \n", n);
+ } else {
+ socket_log_print(log_fd, &file_list, buf);
+ memset(buf, 0, sizeof(buf));
+ }
+ }
+ }
+ }
+ }
+ close(listen_fd);
+ close(log_fd);
+ unlink(_MOPEN_RILD_SOCKET);
+ printf("%s exit \n", __FUNCTION__);
+ pthread_exit(NULL);
+
+ return NULL;
+}
diff --git a/mbtk/mbtk_logd/syslog.h b/mbtk/mbtk_logd/syslog.h
new file mode 100755
index 0000000..b682ced
--- /dev/null
+++ b/mbtk/mbtk_logd/syslog.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1
+ * as published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __SYSLOG_H
+#define __SYSLOG_H
+
+enum {
+ SOURCE_KLOG = 0,
+ SOURCE_SYSLOG = 1,
+ SOURCE_INTERNAL = 2,
+ SOURCE_ANY = 0xff,
+};
+
+struct log_head {
+ unsigned int size;
+ unsigned int id;
+ int priority;
+ int source;
+ struct timespec ts;
+ char data[];
+};
+
+void log_init(int log_size);
+void log_shutdown(void);
+
+typedef void (*log_list_cb)(struct log_head *h);
+struct log_head* log_list(int count, struct log_head *h);
+int log_buffer_init(int size);
+void log_add(char *buf, int size, int source);
+void ubus_notify_log(struct log_head *l);
+
+#endif
diff --git a/mbtk/mbtk_logd/syslog_read.c b/mbtk/mbtk_logd/syslog_read.c
new file mode 100755
index 0000000..3cae9e9
--- /dev/null
+++ b/mbtk/mbtk_logd/syslog_read.c
@@ -0,0 +1,350 @@
+/*
+ * Copyright (C) 2013 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1
+ * as published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <fcntl.h>
+#include <time.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#define SYSLOG_NAMES
+#include <syslog.h>
+
+#include <libubox/ustream.h>
+#include <libubox/blobmsg_json.h>
+#include <libubox/usock.h>
+#include <libubox/uloop.h>
+#include "libubus.h"
+#include "syslog.h"
+#include "log_config.h"
+
+enum {
+ LOG_STDOUT,
+ LOG_FILE,
+ LOG_NET,
+};
+
+enum {
+ LOG_MSG,
+ LOG_ID,
+ LOG_PRIO,
+ LOG_SOURCE,
+ LOG_TIME,
+ __LOG_MAX
+};
+
+static const struct blobmsg_policy log_policy[] = {
+ [LOG_MSG] = { .name = "msg", .type = BLOBMSG_TYPE_STRING },
+ [LOG_ID] = { .name = "id", .type = BLOBMSG_TYPE_INT32 },
+ [LOG_PRIO] = { .name = "priority", .type = BLOBMSG_TYPE_INT32 },
+ [LOG_SOURCE] = { .name = "source", .type = BLOBMSG_TYPE_INT32 },
+ [LOG_TIME] = { .name = "time", .type = BLOBMSG_TYPE_INT64 },
+};
+
+static struct uloop_timeout retry;
+static struct uloop_fd sender;
+static const char *log_file, *log_ip, *log_port, *log_prefix, *pid_file, *hostname;
+static int log_type = LOG_STDOUT;
+static int log_size = 1 * 1024 * 1024, log_udp, log_follow = 0;
+static struct file_list_t file_list;
+static struct filter_list_t *filter_log = NULL;
+static char tmp_log[48] = {0};
+
+static const char* getcodetext(int value, CODE *codetable) {
+ CODE *i;
+
+ if (value >= 0)
+ for (i = codetable; i->c_val != -1; i++)
+ if (i->c_val == value)
+ return (i->c_name);
+ return "<unknown>";
+};
+
+static void log_handle_reconnect(struct uloop_timeout *timeout)
+{
+ sender.fd = usock((log_udp) ? (USOCK_UDP) : (USOCK_TCP), log_ip, log_port);
+ if (sender.fd < 0) {
+ fprintf(stderr, "failed to connect: %s\n", strerror(errno));
+ uloop_timeout_set(&retry, 1000);
+ } else {
+ uloop_fd_add(&sender, ULOOP_READ);
+ syslog(0, "Logread connected to %s:%s\n", log_ip, log_port);
+ }
+}
+
+static void log_handle_fd(struct uloop_fd *u, unsigned int events)
+{
+ if (u->eof) {
+ uloop_fd_delete(u);
+ close(sender.fd);
+ sender.fd = -1;
+ uloop_timeout_set(&retry, 1000);
+ }
+}
+
+static int filter_char_to_pri(char c)
+{
+ switch (c) {
+ case 'v':
+ return 8;
+ case 'd':
+ return LOG_DEBUG;
+ case 'i':
+ return LOG_INFO;
+ case 'w':
+ return LOG_WARNING;
+ case 'e':
+ return LOG_ERR;
+ case 'f':
+ return LOG_ALERT;
+ case '*':
+ default:
+ return 8;
+ }
+}
+
+static int syslog_fileter_log(int pri, char *tag, struct filter_list_t *filter)
+{
+ struct filter_list_t *_filter = filter;
+
+ while(_filter)
+ {
+ int p = filter_char_to_pri(_filter->priority);
+ if(_filter->tag)
+ {
+ int len = strlen(_filter->tag);
+ // tag and priority
+ if(0 == memcmp(_filter->tag, tag, len) && ((pri < p) || (pri == p)))
+ return 0;
+ }else{ // have no tag
+ if(pri > p)
+ return -1;
+ else
+ return 0;
+ }
+ _filter = _filter->next;
+ }
+
+ return -1;
+}
+static int log_notify(struct blob_attr *msg)
+{
+ struct blob_attr *tb[__LOG_MAX];
+ struct stat s;
+ char buf[512];
+ uint32_t p;
+ char *str;
+ time_t t;
+ char *c, *m;
+
+ if (sender.fd < 0)
+ return 0;
+
+ blobmsg_parse(log_policy, ARRAY_SIZE(log_policy), tb, blob_data(msg), blob_len(msg));
+ if (!tb[LOG_ID] || !tb[LOG_PRIO] || !tb[LOG_SOURCE] || !tb[LOG_TIME] || !tb[LOG_MSG])
+ return 1;
+
+ if ((log_type == LOG_FILE) && log_size && (!stat(tmp_log, &s)) && (s.st_size > log_size)) {
+ sender.fd = get_rotate_file(sender.fd, log_file, &file_list);
+ if (sender.fd < 0) {
+ fprintf(stderr, "failed to open %s: %s\n", tmp_log, strerror(errno));
+ exit(-1);
+ }
+ }
+
+ m = blobmsg_get_string(tb[LOG_MSG]);
+ t = blobmsg_get_u64(tb[LOG_TIME]) / 1000;
+ c = ctime(&t);
+ p = blobmsg_get_u32(tb[LOG_PRIO]);
+ c[strlen(c) - 1] = '\0';
+ str = blobmsg_format_json(msg, true);
+
+ if(filter_log && syslog_fileter_log(LOG_PRI(p), m, filter_log))
+ {
+ // printf("%s %d: fileter pri:%d tag:%s!\n", __FUNCTION__, __LINE__, p, m);
+ exit(-1);
+ }
+ if (log_type == LOG_NET) {
+ int err;
+
+ snprintf(buf, sizeof(buf), "<%u>", p);
+ strncat(buf, c + 4, 16);
+ if (hostname) {
+ strncat(buf, hostname, sizeof(buf));
+ strncat(buf, " ", sizeof(buf));
+ }
+ if (log_prefix) {
+ strncat(buf, log_prefix, sizeof(buf));
+ strncat(buf, ": ", sizeof(buf));
+ }
+ if (blobmsg_get_u32(tb[LOG_SOURCE]) == SOURCE_KLOG)
+ strncat(buf, "kernel: ", sizeof(buf));
+ strncat(buf, m, sizeof(buf));
+ if (log_udp)
+ err = write(sender.fd, buf, strlen(buf));
+ else
+ err = send(sender.fd, buf, strlen(buf), 0);
+
+ if (err < 0) {
+ syslog(0, "failed to send log data to %s:%s via %s\n",
+ log_ip, log_port, (log_udp) ? ("udp") : ("tcp"));
+ uloop_fd_delete(&sender);
+ close(sender.fd);
+ sender.fd = -1;
+ uloop_timeout_set(&retry, 1000);
+ }
+ } else {
+ snprintf(buf, sizeof(buf), "%s %s.%s%s %s\n",
+ c, getcodetext(LOG_FAC(p) << 3, facilitynames), getcodetext(LOG_PRI(p), prioritynames),
+ (blobmsg_get_u32(tb[LOG_SOURCE])) ? ("") : (" kernel:"), m);
+ write(sender.fd, buf, strlen(buf));
+ }
+
+ free(str);
+ if (log_type == LOG_FILE)
+ fsync(sender.fd);
+
+ return 0;
+}
+
+static void logread_fd_data_cb(struct ustream *s, int bytes)
+{
+ while (true) {
+ int len;
+ struct blob_attr *a;
+
+ a = (void*) ustream_get_read_buf(s, &len);
+ if (len < sizeof(*a) || len < blob_len(a) + sizeof(*a))
+ break;
+ log_notify(a);
+ ustream_consume(s, blob_len(a) + sizeof(*a));
+ }
+ if (!log_follow)
+ uloop_end();
+}
+
+static void logread_fd_cb(struct ubus_request *req, int fd)
+{
+ static struct ustream_fd test_fd;
+
+ test_fd.stream.notify_read = logread_fd_data_cb;
+ ustream_fd_init(&test_fd, fd);
+}
+
+static void logread_complete_cb(struct ubus_request *req, int ret)
+{
+}
+
+void* syslog_main(void* argv)
+{
+ static struct ubus_request req;
+ struct ubus_context *ctx;
+ uint32_t id;
+ const char *ubus_socket = NULL;
+ int ch, ret, lines = 0;
+ static struct blob_buf b;
+ int tries = 5;
+ log_config_entry *config = (log_config_entry *)argv;
+
+ pthread_detach(pthread_self());
+
+ if (NULL == argv)
+ return NULL;
+
+ signal(SIGPIPE, SIG_IGN);
+ uloop_init();
+
+ log_file = config->out_path;
+ memset(&file_list, 0, sizeof(struct file_list_t));
+ file_list.total = config->rotate_file_count;
+ if(config->rotate_file_size)
+ log_size = config->rotate_file_size;
+ if(config->ip)
+ {
+ printf("%s %d : %s:%s\n", __FUNCTION__, __LINE__, config->ip, config->port);
+ log_ip = config->ip;
+ log_port = config->port;
+ }
+ filter_log = config->filter_list;
+ // Follow log messages
+ log_follow = 1;
+ ctx = ubus_connect(ubus_socket);
+ if (!ctx) {
+ fprintf(stderr, "Failed to connect to ubus\n");
+ return -1;
+ }
+ ubus_add_uloop(ctx);
+
+ printf("syslog log start...\n");
+ /* ugly ugly ugly ... we need a real reconnect logic */
+ do {
+ ret = ubus_lookup_id(ctx, "log", &id);
+ if (ret) {
+ fprintf(stderr, "Failed to find log object: %s\n", ubus_strerror(ret));
+ sleep(1);
+ continue;
+ }
+
+ blob_buf_init(&b, 0);
+ if (lines)
+ blobmsg_add_u32(&b, "lines", lines);
+ else if (log_follow)
+ blobmsg_add_u32(&b, "lines", 0);
+ if (log_follow) {
+ if (pid_file) {
+ FILE *fp = fopen(pid_file, "w+");
+ if (fp) {
+ fprintf(fp, "%d", getpid());
+ fclose(fp);
+ }
+ }
+ }
+
+ if (log_ip && log_port) {
+ openlog("logread", LOG_PID, LOG_DAEMON);
+ log_type = LOG_NET;
+ sender.cb = log_handle_fd;
+ retry.cb = log_handle_reconnect;
+ uloop_timeout_set(&retry, 1000);
+ } else if (log_file) {
+ log_type = LOG_FILE;
+ // 先将文件保存到 /tmp/log/ 目录下,后面到达 rotate_file_size 后,转移到out_path
+ sprintf(tmp_log, "/tmp/log%s", strstr_tail(log_file, "/"));
+ sender.fd = open(tmp_log, O_CREAT | O_WRONLY| O_APPEND, 0600);
+ if (sender.fd < 0) {
+ fprintf(stderr, "failed to open %s: %s\n", tmp_log, strerror(errno));
+ exit(-1);
+ }
+ } else {
+ sender.fd = STDOUT_FILENO;
+ }
+
+ ubus_invoke_async(ctx, id, "read", b.head, &req);
+ req.fd_cb = logread_fd_cb;
+ req.complete_cb = logread_complete_cb;
+ ubus_complete_request_async(ctx, &req);
+
+ uloop_run();
+ ubus_free(ctx);
+ uloop_done();
+
+ } while (ret && tries--);
+
+ pthread_exit(NULL);
+ return NULL;
+}