Compilation of ubus/ familly now use the offial cmake instead of a rewriten one.

This commit is contained in:
jbnadal
2017-03-20 14:43:00 +01:00
parent b9e31fce39
commit 0e766a04f4
15 changed files with 981 additions and 220 deletions

View File

@@ -1,6 +1,14 @@
config BR2_PACKAGE_LIBUBOX
bool "libubox"
default n
depends on !BR2_STATIC_LIBS
select BR2_PACKAGE_JSON_C
help
New Version of the ubox library.
This library originates from the OpenWrt project to
handle the configuration file infrastructure, but can
also be used for the same purposes in projects other
than OpenWrt.
http://nbd.name/gitweb.cgi?p=luci2/libubox.git;a=summary
comment "libubox needs a toolchain w/ dynamic library"
depends on BR2_STATIC_LIBS

View File

@@ -6,14 +6,17 @@
LIBUBOX_VERSION:= 2016-11-29
LIBUBOX_SITE = $(TOPDIR)/../../src/3P/libubox/builders/cmake
LIBUBOX_SITE = $(TOPDIR)/../../src/3P/libubox
LIBUBOX_SITE_METHOD = local
LIBUBOX_LICENSE = LGPLv2.1, GPLv2, BSD-3c, MIT
LIBUBOX_INSTALL_STAGING = YES
LIBUBOX_DEPENDENCIES = json-c
LIBUBOX_CONF = SRC_DIR=$(TOPDIR)/../..
LIBUBOX_CONF_OPTS +=-DBUILD_LUA=OFF
LIBUBOX_CONF_ENV = $(LIBUBOX_CONF)
LIBUBOX_MAKE_ENV = $(LIBUBOX_CONF)
LIBUBOX_CONF_OPTS += -DMODULE_PATH=$(TOPDIR)/../../bsp/cmake-modules -DCMAKE_BUILD_TYPE=$(BUILD_TYPE)

View File

@@ -6,7 +6,7 @@
UBOX_VERSION:= 2017.01.15
UBOX_SITE = $(TOPDIR)/../../src/3P/ubox/builders/cmake
UBOX_SITE = $(TOPDIR)/../../src/3P/ubox
UBOX_SITE_METHOD = local
UBOX_INSTALL_STAGING = YES

View File

@@ -2,5 +2,15 @@ config BR2_PACKAGE_UBUS
bool "ubus"
default n
select BR2_PACKAGE_LIBUBOX
select BR2_PACKAGE_JSON_C
help
Next Version of the ubus daemon programs.
IPC/RPC bus that allows communication between processes.
It consists of few parts including a daemon (ubusd), a library
(libubus) and a command line interface (ubus). Although created
for the OpenWRT project, it can be used as a general IPC/RPC
mechanism in other projects.
* Select BR2_PACKAGE_LUA_5_1 if you want to have Lua support.
https://wiki.openwrt.org/doc/techref/ubus

View File

@@ -6,7 +6,7 @@
UBUS_VERSION:= 2017.01.22
UBUS_SITE = $(TOPDIR)/../../src/3P/ubus/builders/cmake
UBUS_SITE = $(TOPDIR)/../../src/3P/ubus
UBUS_SITE_METHOD = local
UBUS_INSTALL_STAGING = YES

View File

@@ -6,7 +6,7 @@
UCI_VERSION:= 2016.07.04
UCI_SITE = $(TOPDIR)/../../src/3P/uci/builders/cmake
UCI_SITE = $(TOPDIR)/../../src/3P/uci
UCI_SITE_METHOD = local
UCI_INSTALL_STAGING = YES
@@ -14,6 +14,8 @@ UCI_DEPENDENCIES = libubox ubus
UCI_CONF = SRC_DIR=$(TOPDIR)/../..
UCI_CONF_OPTS +=-DBUILD_LUA=OFF
UCI_CONF_ENV = $(UCI_CONF)
UCI_MAKE_ENV = $(UCI_CONF)
UCI_CONF_OPTS += -DMODULE_PATH=$(TOPDIR)/../../bsp/cmake-modules -DCMAKE_BUILD_TYPE=$(BUILD_TYPE)

View File

@@ -1,6 +1,6 @@
#
# Automatically generated file; DO NOT EDIT.
# Buildroot 2016.08.1-g2fc32dd-dirty Configuration
# Buildroot 2016.08.1-gb9e31fc-dirty Configuration
#
BR2_HAVE_DOT_CONFIG=y
BR2_HOST_GCC_AT_LEAST_4_6=y
@@ -811,6 +811,12 @@ BR2_PACKAGE_GAUCHE_ARCH_SUPPORTS=y
# BR2_PACKAGE_JAMVM is not set
# BR2_PACKAGE_JIMTCL is not set
# BR2_PACKAGE_LUA is not set
# BR2_PACKAGE_LUA_5_1 is not set
# BR2_PACKAGE_LUA_5_2 is not set
# BR2_PACKAGE_LUA_5_3 is not set
# BR2_PACKAGE_LUA_EDITING_NONE is not set
# BR2_PACKAGE_LUA_READLINE is not set
# BR2_PACKAGE_LUA_LINENOISE is not set
BR2_PACKAGE_LUAJIT_ARCH_SUPPORTS=y
# BR2_PACKAGE_LUAJIT is not set
# BR2_PACKAGE_MICROPYTHON is not set

View File

@@ -1,67 +0,0 @@
cmake_minimum_required (VERSION 3.0)
project (libubox)
set (CMAKE_MODULE_PATH "${MODULE_PATH}")
set(DISABLE_TARGET_OPTIMIZATION ON)
include (br)
ADD_DEFINITIONS(-DJSONC)
include_directories ($ENV{SRC_DIR}/src/3P/libubox/)
file (
GLOB_RECURSE
source_files
$ENV{SRC_DIR}/src/3P/libubox/avl.c
$ENV{SRC_DIR}/src/3P/libubox/avl-cmp.c
$ENV{SRC_DIR}/src/3P/libubox/blob.c
$ENV{SRC_DIR}/src/3P/libubox/blobmsg.c
$ENV{SRC_DIR}/src/3P/libubox/uloop.c
$ENV{SRC_DIR}/src/3P/libubox/usock.c
$ENV{SRC_DIR}/src/3P/libubox/ustream.c
$ENV{SRC_DIR}/src/3P/libubox/ustream-fd.c
$ENV{SRC_DIR}/src/3P/libubox/vlist.c
$ENV{SRC_DIR}/src/3P/libubox/utils.c
$ENV{SRC_DIR}/src/3P/libubox/safe_list.c
$ENV{SRC_DIR}/src/3P/libubox/runqueue.c
$ENV{SRC_DIR}/src/3P/libubox/md5.c
$ENV{SRC_DIR}/src/3P/libubox/kvlist.c
$ENV{SRC_DIR}/src/3P/libubox/ulog.c
$ENV{SRC_DIR}/src/3Plibubox/base64.c
)
add_library (ubox SHARED ${source_files})
target_link_libraries (ubox
LINK_PUBLIC
json-c
rt
pthread
)
target_include_directories (ubox PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
file (GLOB ubox_headers $ENV{SRC_DIR}/src/3P/libubox/*.h)
install (FILES ${ubox_headers} DESTINATION include/libubox)
add_library (json_script SHARED $ENV{SRC_DIR}/src/3P/libubox/json_script.c)
target_link_libraries (json_script ubox)
add_library (blobmsg_json SHARED $ENV{SRC_DIR}/src/3P/libubox/blobmsg_json.c)
target_link_libraries (blobmsg_json json-c)
add_executable (jshn $ENV{SRC_DIR}/src/3P/libubox/jshn.c)
target_link_libraries (jshn ubox blobmsg_json json-c)
install (TARGETS ubox json_script blobmsg_json
LIBRARY DESTINATION ../lib
)
install (TARGETS jshn RUNTIME DESTINATION bin)
install (FILES $ENV{SRC_DIR}/src/3P/libubox/sh/jshn.sh
DESTINATION share/libubox)

View File

@@ -1,30 +0,0 @@
cmake_minimum_required (VERSION 3.0)
project (ubox)
ADD_DEFINITIONS(-Os -ggdb -Wall -Werror --std=gnu99 -Wmissing-declarations)
set (CMAKE_MODULE_PATH "${MODULE_PATH}")
set(DISABLE_TARGET_OPTIMIZATION ON)
include (br)
# Logd
add_executable (logd
$ENV{SRC_DIR}/src/3P/ubox/log/logd.c
$ENV{SRC_DIR}/src/3P/ubox/log/syslog.c)
target_link_libraries (logd ubox ubus)
install (TARGETS logd RUNTIME DESTINATION sbin)
# Logread
add_executable (logread
$ENV{SRC_DIR}/src/3P/ubox/log/logread.c)
target_link_libraries (logread ubox ubus json-c blobmsg_json)
install (TARGETS logread RUNTIME DESTINATION sbin)
# kmodloader
add_executable (kmodloader
$ENV{SRC_DIR}/src/3P/ubox/kmodloader.c)
target_link_libraries (kmodloader ubox)
install (TARGETS kmodloader RUNTIME DESTINATION ../sbin)

238
src/3P/ubox/log/logd.c Normal file
View File

@@ -0,0 +1,238 @@
/*
* 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 <stdio.h>
#include <unistd.h>
#include <syslog.h>
#include <unistd.h>
#include <linux/types.h>
#include <libubox/uloop.h>
#include <libubox/blobmsg.h>
#include <libubox/list.h>
#include <libubox/ustream.h>
#include <libubus.h>
#include "syslog.h"
int debug = 0;
static struct blob_buf b;
static struct ubus_auto_conn conn;
static LIST_HEAD(clients);
enum {
READ_LINES,
READ_STREAM,
__READ_MAX
};
static const struct blobmsg_policy read_policy[__READ_MAX] = {
[READ_LINES] = { .name = "lines", .type = BLOBMSG_TYPE_INT32 },
[READ_STREAM] = { .name = "stream", .type = BLOBMSG_TYPE_BOOL },
};
static const struct blobmsg_policy write_policy =
{ .name = "event", .type = BLOBMSG_TYPE_STRING };
struct client {
struct list_head list;
struct ustream_fd s;
int fd;
};
static void
client_close(struct ustream *s)
{
struct client *cl = container_of(s, struct client, s.stream);
list_del(&cl->list);
ustream_free(s);
close(cl->fd);
free(cl);
}
static void client_notify_state(struct ustream *s)
{
client_close(s);
}
static void
log_fill_msg(struct blob_buf *b, struct log_head *l)
{
blobmsg_add_string(b, "msg", l->data);
blobmsg_add_u32(b, "id", l->id);
blobmsg_add_u32(b, "priority", l->priority);
blobmsg_add_u32(b, "source", l->source);
blobmsg_add_u64(b, "time", l->ts.tv_sec * 1000LL);
}
static int
read_log(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method,
struct blob_attr *msg)
{
struct client *cl;
struct blob_attr *tb[__READ_MAX];
struct log_head *l;
int count = 0;
int fds[2];
int ret;
bool stream = true;
void *c, *e;
if (!stream)
count = 100;
if (msg) {
blobmsg_parse(read_policy, __READ_MAX, tb, blob_data(msg), blob_len(msg));
if (tb[READ_LINES])
count = blobmsg_get_u32(tb[READ_LINES]);
if (tb[READ_STREAM])
stream = blobmsg_get_bool(tb[READ_STREAM]);
}
if (pipe(fds) == -1) {
fprintf(stderr, "logd: failed to create pipe: %s\n", strerror(errno));
return -1;
}
l = log_list(count, NULL);
if (stream) {
ubus_request_set_fd(ctx, req, fds[0]);
cl = calloc(1, sizeof(*cl));
cl->s.stream.notify_state = client_notify_state;
cl->fd = fds[1];
ustream_fd_init(&cl->s, cl->fd);
list_add(&cl->list, &clients);
while ((!tb[READ_LINES] || count) && l) {
blob_buf_init(&b, 0);
log_fill_msg(&b, l);
l = log_list(count, l);
ret = ustream_write(&cl->s.stream, (void *) b.head, blob_len(b.head) + sizeof(struct blob_attr), false);
if (ret < 0)
break;
}
} else {
blob_buf_init(&b, 0);
c = blobmsg_open_array(&b, "log");
while ((!tb[READ_LINES] || count) && l) {
e = blobmsg_open_table(&b, NULL);
log_fill_msg(&b, l);
blobmsg_close_table(&b, e);
l = log_list(count, l);
}
blobmsg_close_array(&b, c);
ubus_send_reply(ctx, req, b.head);
}
blob_buf_free(&b);
return 0;
}
static int
write_log(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method,
struct blob_attr *msg)
{
struct blob_attr *tb;
char *event;
if (msg) {
blobmsg_parse(&write_policy, 1, &tb, blob_data(msg), blob_len(msg));
if (tb) {
event = blobmsg_get_string(tb);
log_add(event, strlen(event) + 1, SOURCE_SYSLOG);
}
}
return 0;
}
static const struct ubus_method log_methods[] = {
UBUS_METHOD("read", read_log, read_policy),
{ .name = "write", .handler = write_log, .policy = &write_policy, .n_policy = 1 },
};
static struct ubus_object_type log_object_type =
UBUS_OBJECT_TYPE("log", log_methods);
static struct ubus_object log_object = {
.name = "log",
.type = &log_object_type,
.methods = log_methods,
.n_methods = ARRAY_SIZE(log_methods),
};
void
ubus_notify_log(struct log_head *l)
{
struct client *c;
if (list_empty(&clients))
return;
blob_buf_init(&b, 0);
blobmsg_add_string(&b, "msg", l->data);
blobmsg_add_u32(&b, "id", l->id);
blobmsg_add_u32(&b, "priority", l->priority);
blobmsg_add_u32(&b, "source", l->source);
blobmsg_add_u64(&b, "time", (((__u64) l->ts.tv_sec) * 1000) + (l->ts.tv_nsec / 1000000));
list_for_each_entry(c, &clients, list)
ustream_write(&c->s.stream, (void *) b.head, blob_len(b.head) + sizeof(struct blob_attr), false);
blob_buf_free(&b);
}
static void
ubus_connect_handler(struct ubus_context *ctx)
{
int ret;
ret = ubus_add_object(ctx, &log_object);
if (ret) {
fprintf(stderr, "Failed to add object: %s\n", ubus_strerror(ret));
exit(1);
}
fprintf(stderr, "log: connected to ubus\n");
}
int
main(int argc, char **argv)
{
int ch, log_size = 16;
signal(SIGPIPE, SIG_IGN);
while ((ch = getopt(argc, argv, "S:")) != -1) {
switch (ch) {
case 'S':
log_size = atoi(optarg);
if (log_size < 1)
log_size = 16;
break;
}
}
log_size *= 1024;
uloop_init();
log_init(log_size);
conn.cb = ubus_connect_handler;
ubus_auto_connect(&conn);
uloop_run();
log_shutdown();
uloop_done();
ubus_auto_shutdown(&conn);
return 0;
}

359
src/3P/ubox/log/logread.c Normal file
View File

@@ -0,0 +1,359 @@
/*
* 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 <regex.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"
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 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 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(LOG_INFO, "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 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;
int ret = 0;
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(log_file, &s)) && (s.st_size > log_size)) {
char *old = malloc(strlen(log_file) + 5);
close(sender.fd);
if (old) {
sprintf(old, "%s.old", log_file);
rename(log_file, old);
free(old);
}
sender.fd = open(log_file, O_CREAT | O_WRONLY | O_APPEND, 0600);
if (sender.fd < 0) {
fprintf(stderr, "failed to open %s: %s\n", log_file, strerror(errno));
exit(-1);
}
}
m = blobmsg_get_string(tb[LOG_MSG]);
if (regexp_pattern &&
regexec(&regexp_preg, m, 0, NULL, 0) == REG_NOMATCH)
return 0;
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 (log_type == LOG_NET) {
int err;
snprintf(buf, sizeof(buf), "<%u>", p);
strncat(buf, c + 4, 16);
if (hostname) {
strncat(buf, hostname, sizeof(buf) - strlen(buf) - 1);
strncat(buf, " ", sizeof(buf) - strlen(buf) - 1);
}
if (log_prefix) {
strncat(buf, log_prefix, sizeof(buf) - strlen(buf) - 1);
strncat(buf, ": ", sizeof(buf) - strlen(buf) - 1);
}
if (blobmsg_get_u32(tb[LOG_SOURCE]) == SOURCE_KLOG)
strncat(buf, "kernel: ", sizeof(buf) - strlen(buf) - 1);
strncat(buf, m, sizeof(buf) - strlen(buf) - 1);
if (log_udp)
err = write(sender.fd, buf, strlen(buf));
else {
size_t buflen = strlen(buf);
if (!log_trailer_null)
buf[buflen] = '\n';
err = send(sender.fd, buf, buflen + 1, 0);
}
if (err < 0) {
syslog(LOG_INFO, "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);
ret = write(sender.fd, buf, strlen(buf));
}
free(str);
if (log_type == LOG_FILE)
fsync(sender.fd);
return ret;
}
static int usage(const char *prog)
{
fprintf(stderr, "Usage: %s [options]\n"
"Options:\n"
" -s <path> Path to ubus socket\n"
" -l <count> Got only the last 'count' messages\n"
" -e <pattern> Filter messages with a regexp\n"
" -r <server> <port> Stream message to a server\n"
" -F <file> Log file\n"
" -S <bytes> Log size\n"
" -p <file> PID file\n"
" -h <hostname> Add hostname to the message\n"
" -P <prefix> Prefix custom text to streamed messages\n"
" -f Follow log messages\n"
" -u Use UDP as the protocol\n"
" -0 Use \\0 instead of \\n as trailer when using TCP\n"
"\n", prog);
return 1;
}
static void logread_fd_data_cb(struct ustream *s, int bytes)
{
while (true) {
struct blob_attr *a;
int len, cur_len;
a = (void*) ustream_get_read_buf(s, &len);
if (len < sizeof(*a))
break;
cur_len = blob_len(a) + sizeof(*a);
if (len < cur_len)
break;
log_notify(a);
ustream_consume(s, cur_len);
}
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);
}
int main(int argc, char **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;
signal(SIGPIPE, SIG_IGN);
while ((ch = getopt(argc, argv, "u0fcs:l:r:F:p:S:P:h:e:")) != -1) {
switch (ch) {
case 'u':
log_udp = 1;
break;
case '0':
log_trailer_null = 1;
break;
case 's':
ubus_socket = optarg;
break;
case 'r':
log_ip = optarg++;
log_port = argv[optind++];
break;
case 'F':
log_file = optarg;
break;
case 'p':
pid_file = optarg;
break;
case 'P':
log_prefix = optarg;
break;
case 'f':
log_follow = 1;
break;
case 'l':
lines = atoi(optarg);
break;
case 'S':
log_size = atoi(optarg);
if (log_size < 1)
log_size = 1;
log_size *= 1024;
break;
case 'h':
hostname = optarg;
break;
case 'e':
if (!regcomp(&regexp_preg, optarg, REG_NOSUB)) {
regexp_pattern = optarg;
}
break;
default:
return usage(*argv);
}
}
uloop_init();
ctx = ubus_connect(ubus_socket);
if (!ctx) {
fprintf(stderr, "Failed to connect to ubus\n");
return -1;
}
ubus_add_uloop(ctx);
/* 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);
blobmsg_add_u8(&b, "stream", 1);
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;
sender.fd = open(log_file, O_CREAT | O_WRONLY| O_APPEND, 0600);
if (sender.fd < 0) {
fprintf(stderr, "failed to open %s: %s\n", log_file, strerror(errno));
exit(-1);
}
} else {
sender.fd = STDOUT_FILENO;
}
ubus_invoke_async(ctx, id, "read", b.head, &req);
req.fd_cb = logread_fd_cb;
ubus_complete_request_async(ctx, &req);
uloop_run();
ubus_free(ctx);
uloop_done();
} while (ret && tries--);
return ret;
}

305
src/3P/ubox/log/syslog.c Normal file
View File

@@ -0,0 +1,305 @@
/*
* 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 <linux/un.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <regex.h>
#include <time.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <syslog.h>
#include <libubox/uloop.h>
#include <libubox/usock.h>
#include <libubox/ustream.h>
#include "syslog.h"
#define LOG_DEFAULT_SIZE (16 * 1024)
#define LOG_DEFAULT_SOCKET "/dev/log"
#define LOG_LINE_LEN 256
#define SYSLOG_PADDING 16
#define KLOG_DEFAULT_PROC "/proc/kmsg"
#define PAD(x) (x % 4) ? (((x) - (x % 4)) + 4) : (x)
static char *log_dev = LOG_DEFAULT_SOCKET;
static int log_size = LOG_DEFAULT_SIZE;
static struct log_head *log, *log_end, *oldest, *newest;
static int current_id = 0;
static regex_t pat_prio;
static regex_t pat_tstamp;
static struct log_head*
log_next(struct log_head *h, int size)
{
struct log_head *n = (struct log_head *) &h->data[PAD(sizeof(struct log_head) + size)];
return (n >= log_end) ? (log) : (n);
}
void
log_add(char *buf, int size, int source)
{
regmatch_t matches[4];
struct log_head *next;
int priority = 0;
int ret;
/* bounce out if we don't have init'ed yet (regmatch etc will blow) */
if (!log) {
fprintf(stderr, "%s", buf);
return;
}
/* strip trailing newline */
if (buf[size - 2] == '\n') {
buf[size - 2] = '\0';
size -= 1;
}
/* strip the priority */
ret = regexec(&pat_prio, buf, 3, matches, 0);
if (!ret) {
priority = atoi(&buf[matches[1].rm_so]);
size -= matches[2].rm_so;
buf += matches[2].rm_so;
}
#if 0
/* strip kernel timestamp */
ret = regexec(&pat_tstamp,buf, 4, matches, 0);
if ((source == SOURCE_KLOG) && !ret) {
size -= matches[3].rm_so;
buf += matches[3].rm_so;
}
#endif
/* strip syslog timestamp */
if ((source == SOURCE_SYSLOG) && (size > SYSLOG_PADDING) && (buf[SYSLOG_PADDING - 1] == ' ')) {
size -= SYSLOG_PADDING;
buf += SYSLOG_PADDING;
}
//fprintf(stderr, "-> %d - %s\n", priority, buf);
/* find new oldest entry */
next = log_next(newest, size);
if (next > newest) {
while ((oldest > newest) && (oldest <= next) && (oldest != log))
oldest = log_next(oldest, oldest->size);
} else {
//fprintf(stderr, "Log wrap\n");
newest->size = 0;
next = log_next(log, size);
for (oldest = log; oldest <= next; oldest = log_next(oldest, oldest->size))
;
newest = log;
}
/* add the log message */
newest->size = size;
newest->id = current_id++;
newest->priority = priority;
newest->source = source;
clock_gettime(CLOCK_REALTIME, &newest->ts);
strcpy(newest->data, buf);
ubus_notify_log(newest);
newest = next;
}
static void
slog_cb(struct ustream *s, int bytes)
{
struct ustream_buf *buf = s->r.head;
char *str;
int len;
do {
str = ustream_get_read_buf(s, NULL);
if (!str)
break;
len = strlen(buf->data);
if (!len) {
bytes -= 1;
ustream_consume(s, 1);
continue;
}
log_add(buf->data, len + 1, SOURCE_SYSLOG);
ustream_consume(s, len);
bytes -= len;
} while (bytes > 0);
}
static void
klog_cb(struct ustream *s, int bytes)
{
struct ustream_buf *buf = s->r.head;
char *newline, *str;
int len;
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;
log_add(buf->data, len, SOURCE_KLOG);
ustream_consume(s, len);
} while (1);
}
struct ustream_fd slog = {
.stream.string_data = true,
.stream.notify_read = slog_cb,
};
struct ustream_fd klog = {
.stream.string_data = true,
.stream.notify_read = klog_cb,
};
static int
klog_open(void)
{
int fd;
fd = open(KLOG_DEFAULT_PROC, O_RDONLY | O_NONBLOCK);
if (fd < 0) {
fprintf(stderr, "Failed to open %s\n", KLOG_DEFAULT_PROC);
return -1;
}
fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
ustream_fd_init(&klog, fd);
return 0;
}
static int
syslog_open(void)
{
int fd;
unlink(log_dev);
fd = usock(USOCK_UNIX | USOCK_UDP | USOCK_SERVER | USOCK_NONBLOCK, log_dev, NULL);
if (fd < 0) {
fprintf(stderr,"Failed to open %s\n", log_dev);
return -1;
}
chmod(log_dev, 0666);
ustream_fd_init(&slog, fd);
return 0;
}
struct log_head*
log_list(int count, struct log_head *h)
{
unsigned int min = count;
if (count)
min = (count < current_id) ? (current_id - count) : (0);
if (!h && oldest->id >= min)
return oldest;
if (!h)
h = oldest;
while (h != newest) {
h = log_next(h, h->size);
if (!h->size && (h > newest))
h = log;
if (h->id >= min && (h != newest))
return h;
}
return NULL;
}
int
log_buffer_init(int size)
{
struct log_head *_log = malloc(size);
if (!_log) {
fprintf(stderr, "Failed to initialize log buffer with size %d\n", log_size);
return -1;
}
memset(_log, 0, size);
if (log && ((log_size + sizeof(struct log_head)) < size)) {
struct log_head *start = _log;
struct log_head *end = ((void*) _log) + size;
struct log_head *l;
l = log_list(0, NULL);
while ((start < end) && l && l->size) {
memcpy(start, l, PAD(sizeof(struct log_head) + l->size));
start = (struct log_head *) &l->data[PAD(l->size)];
l = log_list(0, l);
}
free(log);
newest = start;
newest->size = 0;
oldest = log = _log;
log_end = ((void*) log) + size;
} else {
oldest = newest = log = _log;
log_end = ((void*) log) + size;
}
log_size = size;
return 0;
}
void
log_init(int _log_size)
{
if (_log_size > 0)
log_size = _log_size;
regcomp(&pat_prio, "^<([0-9]*)>(.*)", REG_EXTENDED);
regcomp(&pat_tstamp, "^\[[ 0]*([0-9]*).([0-9]*)] (.*)", REG_EXTENDED);
if (log_buffer_init(log_size)) {
fprintf(stderr, "Failed to allocate log memory\n");
exit(-1);
}
syslog_open();
klog_open();
openlog("sysinit", LOG_CONS, LOG_DAEMON);
}
void
log_shutdown(void)
{
ustream_free(&slog.stream);
ustream_free(&klog.stream);
close(slog.fd.fd);
close(klog.fd.fd);
free(log);
regfree(&pat_prio);
regfree(&pat_tstamp);
}

42
src/3P/ubox/log/syslog.h Normal file
View File

@@ -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

View File

@@ -1,68 +0,0 @@
cmake_minimum_required(VERSION 3.0)
project (ubus)
set (CMAKE_MODULE_PATH "${MODULE_PATH}")
set(DISABLE_TARGET_OPTIMIZATION ON)
include (br)
include_directories ($ENV{SRC_DIR}/src/3P/ubus)
ADD_DEFINITIONS (-Werror --std=gnu99 -Wmissing-declarations -D_GNU_SOURCE)
ADD_DEFINITIONS (-DUBUS_MAX_MSGLEN=1048576)
ADD_DEFINITIONS (-DUBUS_UNIX_SOCKET="/tmp/ubus.sock")
# ubus library
file (
GLOB_RECURSE
source_files
$ENV{SRC_DIR}/src/3P/ubus/libubus.c
$ENV{SRC_DIR}/src/3P/ubus/libubus-io.c
$ENV{SRC_DIR}/src/3P/ubus/libubus-obj.c
$ENV{SRC_DIR}/src/3P/ubus/libubus-sub.c
$ENV{SRC_DIR}/src/3P/ubus/libubus-req.c
$ENV{SRC_DIR}/src/3P/ubus/libubus-acl.c
)
# Library
add_library (ubus SHARED ${source_files})
target_link_libraries (ubus LINK_PUBLIC ubox)
target_include_directories (ubus PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
install (TARGETS ubus LIBRARY DESTINATION local/lib)
file (GLOB ubus_headers $ENV{SRC_DIR}/src/3P/ubus/*.h)
install (FILES ${ubus_headers} DESTINATION include/ubus)
# Daemon ubusd
file (
GLOB_RECURSE
ubusd_source_files
$ENV{SRC_DIR}/src/3P/ubus/ubusd.c
$ENV{SRC_DIR}/src/3P/ubus/ubusd_id.c
$ENV{SRC_DIR}/src/3P/ubus/ubusd_obj.c
$ENV{SRC_DIR}/src/3P/ubus/ubusd_proto.c
$ENV{SRC_DIR}/src/3P/ubus/ubusd_event.c
$ENV{SRC_DIR}/src/3P/ubus/ubusd_acl.c
$ENV{SRC_DIR}/src/3P/ubus/ubusd_monitor.c
)
# Daemon ubusd
add_executable (ubusd ${ubusd_source_files})
target_link_libraries (ubusd ubox blobmsg_json)
install (TARGETS ubusd RUNTIME DESTINATION ../sbin)
# cmd line tool.
add_executable (ucli $ENV{SRC_DIR}/src/3P/ubus/cli.c)
set_target_properties (ucli PROPERTIES OUTPUT_NAME ubus)
target_link_libraries (ucli LINK_PUBLIC ubox ubus blobmsg_json)
install (TARGETS ucli RUNTIME DESTINATION bin)

View File

@@ -1,47 +0,0 @@
cmake_minimum_required(VERSION 3.0)
project (uci)
set (CMAKE_MODULE_PATH "${MODULE_PATH}")
set(DISABLE_TARGET_OPTIMIZATION ON)
include (br)
include_directories ($ENV{SRC_DIR}/src/3P/uci)
ADD_DEFINITIONS (-Werror --std=gnu99 -Wmissing-declarations)
CONFIGURE_FILE ($ENV{SRC_DIR}/src/3P/uci/uci_config.h.in $ENV{SRC_DIR}/src/3P/uci/uci_config.h )
# uci library
file (
GLOB_RECURSE
lib_source_files
$ENV{SRC_DIR}/src/3P/uci/libuci.c
$ENV{SRC_DIR}/src/3P/uci/file.c
$ENV{SRC_DIR}/src/3P/uci/util.c
$ENV{SRC_DIR}/src/3P/uci/delta.c
$ENV{SRC_DIR}/src/3P/uci/parse.c
$ENV{SRC_DIR}/src/3P/uci/blob.c
)
# Library
add_library (uci SHARED ${lib_source_files})
target_link_libraries (uci LINK_PUBLIC ubox)
target_include_directories (uci PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
install (TARGETS uci LIBRARY DESTINATION local/lib)
file (GLOB uci_headers $ENV{SRC_DIR}/src/3P/uci/*.h)
install (FILES ${uci_headers} DESTINATION include/uci)
# cmd line tool.
add_executable (uci_cli $ENV{SRC_DIR}/src/3P/uci/cli.c)
set_target_properties (uci_cli PROPERTIES OUTPUT_NAME uci)
target_link_libraries (uci_cli LINK_PUBLIC uci ubox blobmsg_json)
install (TARGETS uci_cli RUNTIME DESTINATION ../sbin)