2 * Copyright (C) 2013 Felix Fietkau <nbd@openwrt.org>
3 * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU Lesser General Public License version 2.1
7 * as published by the Free Software Foundation
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
19 #include <libubox/blobmsg_json.h>
20 #include <libubox/usock.h>
21 #include <libubox/uloop.h>
33 static const struct blobmsg_policy log_policy
[] = {
34 [LOG_MSG
] = { .name
= "msg", .type
= BLOBMSG_TYPE_STRING
},
35 [LOG_ID
] = { .name
= "id", .type
= BLOBMSG_TYPE_INT32
},
36 [LOG_PRIO
] = { .name
= "priority", .type
= BLOBMSG_TYPE_INT32
},
37 [LOG_SOURCE
] = { .name
= "source", .type
= BLOBMSG_TYPE_INT32
},
38 [LOG_TIME
] = { .name
= "time", .type
= BLOBMSG_TYPE_INT64
},
47 static struct ubus_subscriber log_event
;
48 static struct uloop_fd sender
;
50 static void log_handle_remove(struct ubus_context
*ctx
, struct ubus_subscriber
*s
,
53 fprintf(stderr
, "Object %08x went away\n", id
);
56 static int log_notify(struct ubus_context
*ctx
, struct ubus_object
*obj
,
57 struct ubus_request_data
*req
, const char *method
,
58 struct blob_attr
*msg
)
60 struct blob_attr
*tb
[__LOG_MAX
];
66 blobmsg_parse(log_policy
, ARRAY_SIZE(log_policy
), tb
, blob_data(msg
), blob_len(msg
));
67 if (!tb
[LOG_ID
] || !tb
[LOG_PRIO
] || !tb
[LOG_SOURCE
] || !tb
[LOG_TIME
])
70 t
= blobmsg_get_u64(tb
[LOG_TIME
]) / 1000;
72 c
[strlen(c
) - 1] = '\0';
73 str
= blobmsg_format_json(msg
, true);
74 snprintf(buf
, sizeof(buf
), "%s - %s: %s\n",
75 c
, (blobmsg_get_u32(tb
[LOG_SOURCE
])) ? ("syslog") : ("kernel"), method
);
76 write(sender
.fd
, buf
, strlen(buf
));
83 static void follow_log(struct ubus_context
*ctx
, int id
, const char *url
, const char *port
)
90 log_event
.remove_cb
= log_handle_remove
;
91 log_event
.cb
= log_notify
;
92 ret
= ubus_register_subscriber(ctx
, &log_event
);
94 fprintf(stderr
, "Failed to add watch handler: %s\n", ubus_strerror(ret
));
96 ret
= ubus_subscribe(ctx
, &log_event
, id
);
98 fprintf(stderr
, "Failed to add watch handler: %s\n", ubus_strerror(ret
));
101 sender
.fd
= usock(USOCK_TCP
| USOCK_NUMERIC
, url
, port
);
103 fprintf(stderr
, "failed to connect: %s\n", strerror(errno
));
106 uloop_fd_add(&sender
, ULOOP_READ
);
109 sender
.fd
= STDOUT_FILENO
;
122 static const struct blobmsg_policy read_policy
[] = {
123 [READ_LINE
] = { .name
= "lines", .type
= BLOBMSG_TYPE_ARRAY
},
126 static void read_cb(struct ubus_request
*req
, int type
, struct blob_attr
*msg
)
128 struct blob_attr
*cur
;
129 struct blob_attr
*_tb
[__READ_MAX
];
136 blobmsg_parse(read_policy
, ARRAY_SIZE(read_policy
), _tb
, blob_data(msg
), blob_len(msg
));
139 blobmsg_for_each_attr(cur
, _tb
[READ_LINE
], rem
) {
140 struct blob_attr
*tb
[__LOG_MAX
];
143 if (blobmsg_type(cur
) != BLOBMSG_TYPE_TABLE
)
146 blobmsg_parse(log_policy
, ARRAY_SIZE(log_policy
), tb
, blobmsg_data(cur
), blobmsg_data_len(cur
));
147 if (!tb
[LOG_MSG
] || !tb
[LOG_ID
] || !tb
[LOG_PRIO
] || !tb
[LOG_SOURCE
] || !tb
[LOG_TIME
])
150 t
= blobmsg_get_u64(tb
[LOG_TIME
]);
152 c
[strlen(c
) - 1] = '\0';
153 printf("%s - %s: %s\n",
154 c
, (blobmsg_get_u32(tb
[LOG_SOURCE
])) ? ("syslog") : ("kernel"),
155 blobmsg_get_string(tb
[LOG_MSG
]));
159 static int usage(const char *prog
)
161 fprintf(stderr
, "Usage: %s [options]\n"
163 " -s <path> Path to ubus socket\n"
164 " -l <count> Got only the last 'count' messages\n"
165 " -r <server> <port> Stream message to a server\n"
166 " -f Follow log messages\n"
171 int main(int argc
, char **argv
)
173 struct ubus_context
*ctx
;
175 const char *ubus_socket
= NULL
, *url
= NULL
, *port
= NULL
;
176 int ch
, ret
, subscribe
= 0, lines
= 0;
177 static struct blob_buf b
;
179 while ((ch
= getopt(argc
, argv
, "fs:l:r:")) != -1) {
182 ubus_socket
= optarg
;
186 port
= argv
[optind
++];
192 lines
= atoi(optarg
);
199 ctx
= ubus_connect(ubus_socket
);
201 fprintf(stderr
, "Failed to connect to ubus\n");
205 ret
= ubus_lookup_id(ctx
, "log", &id
);
207 fprintf(stderr
, "Failed to find log object: %s\n", ubus_strerror(ret
));
209 if (!subscribe
|| lines
) {
210 blob_buf_init(&b
, 0);
212 blobmsg_add_u32(&b
, "lines", lines
);
213 ubus_invoke(ctx
, id
, "read", b
.head
, read_cb
, 0, 3000);
217 follow_log(ctx
, id
, url
, port
);