X-Git-Url: http://git.openwrt.org/?a=blobdiff_plain;f=cli.c;h=5d2cd4c9cfbcec341028f41dfb480ab4487ca29e;hb=65bb027054def3b94a977229fd6ad62ddd32345b;hp=eea43e38aa8d8da7c38af4e6131a7218c6a72f71;hpb=6cd8912f102e721ea10ac13a1885fb9127cb4951;p=project%2Fubus.git diff --git a/cli.c b/cli.c index eea43e3..5d2cd4c 100644 --- a/cli.c +++ b/cli.c @@ -17,6 +17,7 @@ #include "libubus.h" static struct blob_buf b; +static int listen_timeout; static int timeout = 30; static bool simple_output = false; static int verbose = 0; @@ -46,7 +47,7 @@ static const char *format_type(void *priv, struct blob_attr *attr) [BLOBMSG_TYPE_TABLE] = "\"Table\"", }; const char *type = NULL; - int typeid; + size_t typeid; if (blob_id(attr) != BLOBMSG_TYPE_INT32) return NULL; @@ -64,7 +65,7 @@ static void receive_list_result(struct ubus_context *ctx, struct ubus_object_dat { struct blob_attr *cur; char *s; - int rem; + size_t rem; if (simple_output || !verbose) { printf("%s\n", obj->path); @@ -94,8 +95,7 @@ static void receive_call_result_data(struct ubus_request *req, int type, struct free(str); } -static void receive_event(struct ubus_context *ctx, struct ubus_event_handler *ev, - const char *type, struct blob_attr *msg) +static void print_event(const char *type, struct blob_attr *msg) { char *str; @@ -105,6 +105,37 @@ static void receive_event(struct ubus_context *ctx, struct ubus_event_handler *e free(str); } +static int receive_request(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, + const char *method, struct blob_attr *msg) +{ + print_event(method, msg); + return 0; +} + +static void receive_event(struct ubus_context *ctx, struct ubus_event_handler *ev, + const char *type, struct blob_attr *msg) +{ + print_event(type, msg); +} + +static int ubus_cli_error(char *cmd, int argc, char **argv, int err) +{ + int i; + + if (!simple_output && !isatty(fileno(stderr))) { + fprintf(stderr, "Command failed: ubus %s ", cmd); + for (i = 0; i < argc; i++) { + fprintf(stderr, "%s ", argv[i]); + } + fprintf(stderr, "(%s)\n", ubus_strerror(err)); + + return -err; + } + + return err; +} + static int ubus_cli_list(struct ubus_context *ctx, int argc, char **argv) { const char *path = NULL; @@ -128,27 +159,53 @@ static int ubus_cli_call(struct ubus_context *ctx, int argc, char **argv) blob_buf_init(&b, 0); if (argc == 3 && !blobmsg_add_json_from_string(&b, argv[2])) { - if (!simple_output) - fprintf(stderr, "Failed to parse message data\n"); - return -1; + return ubus_cli_error("call", argc, argv, UBUS_STATUS_PARSE_ERROR); } ret = ubus_lookup_id(ctx, argv[0], &id); if (ret) return ret; - return ubus_invoke(ctx, id, argv[1], b.head, receive_call_result_data, NULL, timeout * 1000); + ret = ubus_invoke(ctx, id, argv[1], b.head, receive_call_result_data, NULL, timeout * 1000); + if (ret) + return ubus_cli_error("call", argc, argv, ret); + + return ret; +} + +struct cli_listen_data { + struct uloop_timeout timeout; + bool timed_out; +}; + +static void ubus_cli_listen_timeout(struct uloop_timeout *timeout) +{ + struct cli_listen_data *data = container_of(timeout, struct cli_listen_data, timeout); + data->timed_out = true; + uloop_end(); +} + +static void do_listen(struct ubus_context *ctx, struct cli_listen_data *data) +{ + memset(data, 0, sizeof(*data)); + data->timeout.cb = ubus_cli_listen_timeout; + uloop_init(); + ubus_add_uloop(ctx); + if (listen_timeout) + uloop_timeout_set(&data->timeout, listen_timeout * 1000); + uloop_run(); + uloop_done(); } static int ubus_cli_listen(struct ubus_context *ctx, int argc, char **argv) { - struct ubus_event_handler listener; + struct ubus_event_handler ev = { + .cb = receive_event, + }; + struct cli_listen_data data; const char *event; int ret = 0; - memset(&listener, 0, sizeof(listener)); - listener.cb = receive_event; - if (argc > 0) { event = argv[0]; } else { @@ -157,7 +214,7 @@ static int ubus_cli_listen(struct ubus_context *ctx, int argc, char **argv) } do { - ret = ubus_register_event_handler(ctx, &listener, event); + ret = ubus_register_event_handler(ctx, &ev, event); if (ret) break; @@ -176,14 +233,52 @@ static int ubus_cli_listen(struct ubus_context *ctx, int argc, char **argv) return -1; } - uloop_init(); - ubus_add_uloop(ctx); - uloop_run(); - uloop_done(); + do_listen(ctx, &data); return 0; } +static int ubus_cli_subscribe(struct ubus_context *ctx, int argc, char **argv) +{ + struct ubus_subscriber sub = { + .cb = receive_request, + }; + struct cli_listen_data data; + const char *event; + int ret = 0; + + if (argc > 0) { + event = argv[0]; + } else { + if (!simple_output) + fprintf(stderr, "You need to specify an object to subscribe to\n"); + return -1; + } + + ret = ubus_register_subscriber(ctx, &sub); + for (; !ret && argc > 0; argc--, argv++) { + uint32_t id; + + ret = ubus_lookup_id(ctx, argv[0], &id); + if (ret) + break; + + ret = ubus_subscribe(ctx, &sub, id); + } + + if (ret) { + if (!simple_output) + fprintf(stderr, "Error while registering for event '%s': %s\n", + event, ubus_strerror(ret)); + return -1; + } + + do_listen(ctx, &data); + + return 0; +} + + static int ubus_cli_send(struct ubus_context *ctx, int argc, char **argv) { if (argc < 1 || argc > 2) @@ -192,9 +287,7 @@ static int ubus_cli_send(struct ubus_context *ctx, int argc, char **argv) blob_buf_init(&b, 0); if (argc == 2 && !blobmsg_add_json_from_string(&b, argv[1])) { - if (!simple_output) - fprintf(stderr, "Failed to parse message data\n"); - return -1; + return UBUS_STATUS_PARSE_ERROR; } return ubus_send_event(ctx, argv[0], b.head); @@ -278,17 +371,20 @@ static int ubus_cli_wait_for(struct ubus_context *ctx, int argc, char **argv) uloop_init(); ubus_add_uloop(ctx); - ret = ubus_lookup(ctx, NULL, wait_list_cb, &data); + ret = ubus_register_event_handler(ctx, &data.ev, "ubus.object.add"); if (ret) return ret; if (!data.n_pending) return ret; - ret = ubus_register_event_handler(ctx, &data.ev, "ubus.object.add"); + ret = ubus_lookup(ctx, NULL, wait_list_cb, &data); if (ret) return ret; + if (!data.n_pending) + return ret; + uloop_timeout_set(&data.timeout, timeout * 1000); uloop_run(); uloop_done(); @@ -393,7 +489,7 @@ ubus_cli_monitor_cb(struct ubus_context *ctx, uint32_t seq, struct blob_attr *ms bool send; char *data; - blob_parse(msg, tb, policy, UBUS_MONITOR_MAX); + blob_parse_untrusted(msg, blob_raw_len(msg), tb, policy, UBUS_MONITOR_MAX); if (!tb[UBUS_MONITOR_CLIENT] || !tb[UBUS_MONITOR_PEER] || @@ -441,7 +537,7 @@ static int ubus_cli_monitor(struct ubus_context *ctx, int argc, char **argv) static int add_monitor_type(const char *type) { - int i; + size_t i; for (i = 0; i < ARRAY_SIZE(monitor_types); i++) { if (!monitor_types[i] || strcmp(monitor_types[i], type) != 0) @@ -470,6 +566,7 @@ static int usage(const char *prog) "Commands:\n" " - list [] List objects\n" " - call [] Call an object method\n" + " - subscribe [...] Subscribe to object(s) notifications\n" " - listen [...] Listen for events\n" " - send [] Send an event\n" " - wait_for [...] Wait for multiple objects to appear on ubus\n" @@ -486,6 +583,7 @@ static struct { { "list", ubus_cli_list }, { "call", ubus_cli_call }, { "listen", ubus_cli_listen }, + { "subscribe", ubus_cli_subscribe }, { "send", ubus_cli_send }, { "wait_for", ubus_cli_wait_for }, { "monitor", ubus_cli_monitor }, @@ -495,9 +593,10 @@ int main(int argc, char **argv) { const char *progname, *ubus_socket = NULL; struct ubus_context *ctx; - char *cmd; int ret = 0; - int i, ch; + char *cmd; + size_t i; + int ch; progname = argv[0]; @@ -507,6 +606,7 @@ int main(int argc, char **argv) ubus_socket = optarg; break; case 't': + listen_timeout = atoi(optarg); timeout = atoi(optarg); break; case 'S':