15 #include <sys/types.h>
23 #include <sys/types.h>
24 #include <sys/socket.h>
29 #include <libubox/ustream.h>
30 #include <libubox/blobmsg_json.h>
31 #include <libubox/usock.h>
32 #include <libubox/uloop.h>
36 #define LOGD_CONNECT_RETRY 10
53 static const struct blobmsg_policy
log_policy[] = {
54 [
LOG_MSG] = { .name =
"msg", .type = BLOBMSG_TYPE_STRING },
55 [
LOG_ID] = { .name =
"id", .type = BLOBMSG_TYPE_INT32 },
56 [
LOG_PRIO] = { .name =
"priority", .type = BLOBMSG_TYPE_INT32 },
57 [
LOG_SOURCE] = { .name =
"source", .type = BLOBMSG_TYPE_INT32 },
58 [
LOG_TIME] = { .name =
"time", .type = BLOBMSG_TYPE_INT64 },
61 static struct uloop_timeout
retry;
62 static struct uloop_fd
sender;
86 for (i = codetable; i->c_val != -1; i++)
87 if (i->c_val == value)
96 fprintf(stderr,
"failed to connect: %m\n");
97 uloop_timeout_set(&
retry, 1000);
99 uloop_fd_add(&
sender, ULOOP_READ);
102 syslog(LOG_INFO,
"Logread connected to %s:%s via %s\n",
116 uloop_timeout_set(&
retry, 1000);
140 char *old = malloc(strlen(
log_file) + 5);
150 fprintf(stderr,
"failed to open %s: %m\n",
log_file);
159 m = blobmsg_get_string(tb[
LOG_MSG]);
161 regexec(&
regexp_preg, m, 0, NULL, 0) == REG_NOMATCH)
163 t = blobmsg_get_u64(tb[
LOG_TIME]) / 1000;
165 t_ms = blobmsg_get_u64(tb[
LOG_TIME]) % 1000;
166 snprintf(buf_ts,
sizeof(buf_ts),
"[%lu.%03u] ",
167 (
unsigned long)t, t_ms);
170 c[strlen(c) - 1] =
'\0';
175 snprintf(buf,
sizeof(buf),
"<%u>", p);
176 strncat(buf, c + 4, 16);
178 strncat(buf, buf_ts,
sizeof(buf) - strlen(buf) - 1);
181 strncat(buf,
hostname,
sizeof(buf) - strlen(buf) - 1);
182 strncat(buf,
" ",
sizeof(buf) - strlen(buf) - 1);
185 strncat(buf,
log_prefix,
sizeof(buf) - strlen(buf) - 1);
186 strncat(buf,
": ",
sizeof(buf) - strlen(buf) - 1);
189 strncat(buf,
"kernel: ",
sizeof(buf) - strlen(buf) - 1);
190 strncat(buf, m,
sizeof(buf) - strlen(buf) - 1);
192 err = write(
sender.fd, buf, strlen(buf));
194 size_t buflen = strlen(buf);
197 err = send(
sender.fd, buf, buflen + 1, 0);
201 syslog(LOG_INFO,
"Failed to send log data to %s:%s via %s\n",
206 uloop_timeout_set(&
retry, 1000);
209 snprintf(buf,
sizeof(buf),
"%s %s%s.%s%s %s\n",
213 (blobmsg_get_u32(tb[
LOG_SOURCE])) ? (
"") : (
" kernel:"), m);
214 ret = write(
sender.fd, buf, strlen(buf));
225 fprintf(stderr,
"Usage: %s [options]\n"
227 " -s <path> Path to ubus socket\n"
228 " -l <count> Got only the last 'count' messages\n"
229 " -e <pattern> Filter messages with a regexp\n"
230 " -r <server> <port> Stream message to a server\n"
231 " -F <file> Log file\n"
232 " -S <bytes> Log size\n"
233 " -p <file> PID file\n"
234 " -h <hostname> Add hostname to the message\n"
235 " -P <prefix> Prefix custom text to streamed messages\n"
236 " -z <facility> handle only messages with given facility (0-23), repeatable\n"
237 " -Z <facility> ignore messages with given facility (0-23), repeatable\n"
238 " -f Follow log messages\n"
239 " -u Use UDP as the protocol\n"
240 " -t Add an extra timestamp\n"
241 " -0 Use \\0 instead of \\n as trailer when using TCP\n"
252 a = (
void*) ustream_get_read_buf(s, &len);
253 if (len <
sizeof(*a))
256 cur_len = blob_len(a) +
sizeof(*a);
261 ustream_consume(s, cur_len);
274 static struct ustream_fd test_fd;
276 memset(&test_fd, 0,
sizeof(test_fd));
280 ustream_fd_init(&test_fd, fd);
289 openlog(
"logread", LOG_PID, LOG_DAEMON);
293 uloop_timeout_set(&
retry, 1000);
298 fprintf(stderr,
"failed to open %s: %m\n",
log_file);
302 sender.fd = STDOUT_FILENO;
306 int main(
int argc,
char **argv)
308 struct ubus_context *
ctx;
310 const char *ubus_socket = NULL;
311 int ch, ret, lines = 0;
312 static struct blob_buf
b;
314 signal(SIGPIPE, SIG_IGN);
316 while ((ch = getopt(argc, argv,
"u0fcs:l:z:Z:r:F:p:S:P:h:e:t")) != -1) {
325 ubus_socket = optarg;
344 lines = atoi(optarg);
347 id = strtoul(optarg, NULL, 0) & 0x1f;
351 id = strtoul(optarg, NULL, 0) & 0x1f;
377 ctx = ubus_connect(ubus_socket);
379 fprintf(stderr,
"Failed to connect to ubus\n");
387 fprintf(fp,
"%d", getpid());
392 blob_buf_init(&
b, 0);
393 blobmsg_add_u8(&
b,
"stream", 1);
396 blobmsg_add_u32(&
b,
"lines", lines);
398 blobmsg_add_u32(&
b,
"lines", 0);
402 struct ubus_request req = { 0 };
404 ret = ubus_lookup_id(
ctx,
"log", &
id);
406 fprintf(stderr,
"Failed to find log object: %s\n", ubus_strerror(ret));
413 ubus_invoke_async(
ctx,
id,
"read",
b.head, &req);
415 ubus_complete_request_async(
ctx, &req);
static const char * getcodetext(int value, CODE *codetable)
static const char * log_port
static const char * pid_file
static regex_t regexp_preg
int main(int argc, char **argv)
static void logread_fd_cb(struct ubus_request *req, int fd)
static void logread_fd_state_cb(struct ustream *s)
static int check_facility_filter(int f)
static const char * regexp_pattern
static void logread_setup_output(void)
#define LOGD_CONNECT_RETRY
static struct uloop_fd sender
static const char * hostname
static struct uloop_timeout retry
static const char * log_prefix
static void log_handle_reconnect(struct uloop_timeout *timeout)
static int logd_conn_tries
static int facility_exclude
static int facility_include
static const char * log_ip
static const struct blobmsg_policy log_policy[]
static void logread_fd_data_cb(struct ustream *s, int bytes)
static void log_handle_fd(struct uloop_fd *u, unsigned int events)
static int log_trailer_null
static int usage(const char *prog)
static const char * log_file
static int log_notify(struct blob_attr *msg)
static struct ubus_context * ctx