cli: display proper types for the method signatures
[project/ubus.git] / cli.c
1 #include <libubox/blobmsg_json.h>
2 #include "libubus.h"
3
4 static struct blob_buf b;
5
6 static const char *attr_types[] = {
7 [BLOBMSG_TYPE_INT32] = "\"Integer\"",
8 [BLOBMSG_TYPE_STRING] = "\"String\"",
9 };
10
11 static const char *format_type(void *priv, struct blob_attr *attr)
12 {
13 const char *type = NULL;
14 int typeid;
15
16 if (blob_id(attr) != BLOBMSG_TYPE_INT32)
17 return NULL;
18
19 typeid = blobmsg_get_u32(attr);
20 if (typeid < ARRAY_SIZE(attr_types))
21 type = attr_types[typeid];
22 if (!type)
23 type = "\"(unknown)\"";
24
25 return type;
26 }
27
28 static void receive_lookup(struct ubus_context *ctx, struct ubus_object_data *obj, void *priv)
29 {
30 struct blob_attr *cur;
31 char *s;
32 int rem;
33
34 fprintf(stderr, "'%s' @%08x\n", obj->path, obj->id);
35
36 if (!obj->signature)
37 return;
38
39 blob_for_each_attr(cur, obj->signature, rem) {
40 s = blobmsg_format_json_with_cb(cur, false, format_type, NULL);
41 fprintf(stderr, "\t%s\n", s);
42 free(s);
43 }
44 }
45
46 static void receive_data(struct ubus_request *req, int type, struct blob_attr *msg)
47 {
48 char *str;
49 if (!msg)
50 return;
51
52 str = blobmsg_format_json(msg, true);
53 fprintf(stderr, "%s\n", str);
54 free(str);
55 }
56
57
58 static int usage(char *prog)
59 {
60 fprintf(stderr,
61 "Usage: %s <command> [arguments...]\n"
62 "Commands:\n"
63 " - list [<path>] List objects\n"
64 " - call <path> <method> [<message>] Call an object method\n"
65 " - listen [<path>...] Listen for events\n"
66 "\n", prog);
67 return 1;
68 }
69
70 static void receive_event(struct ubus_context *ctx, struct ubus_event_handler *ev,
71 const char *type, struct blob_attr *msg)
72 {
73 char *str;
74
75 if (msg)
76 str = blobmsg_format_json(msg, true);
77 else
78 str = "";
79
80 fprintf(stderr, "\"%s\":{ %s }\n", type, str);
81 free(str);
82 }
83
84 static int ubus_cli_listen(struct ubus_context *ctx, int argc, char **argv)
85 {
86 static struct ubus_event_handler listener;
87 const char *event;
88 int ret = 0;
89
90 memset(&listener, 0, sizeof(listener));
91 listener.cb = receive_event;
92
93 if (!argc) {
94 event = "*";
95 ret = ubus_register_event_handler(ctx, &listener, NULL);
96 }
97
98 for (;argc;argv++, argc--) {
99 event = argv[0];
100 ret = ubus_register_event_handler(ctx, &listener, argv[0]);
101 if (ret)
102 break;
103 }
104
105 if (ret) {
106 fprintf(stderr, "Error while registering for event '%s': %s\n",
107 event, ubus_strerror(ret));
108 }
109
110 uloop_init();
111 ubus_add_uloop(ctx);
112 uloop_run();
113 uloop_done();
114
115 return 0;
116 }
117
118 int main(int argc, char **argv)
119 {
120 static struct ubus_context *ctx;
121 char *cmd;
122 int ret = 0;
123
124 ctx = ubus_connect(NULL);
125 if (!ctx) {
126 fprintf(stderr, "Failed to connect to ubus\n");
127 return -1;
128 }
129
130 cmd = argv[1];
131 if (argc < 2)
132 return usage(argv[0]);
133
134 if (!strcmp(cmd, "list")) {
135 const char *path = NULL;
136
137 if (argc == 3)
138 path = argv[2];
139
140 ret = ubus_lookup(ctx, path, receive_lookup, NULL);
141 } else if (!strcmp(cmd, "call")) {
142 uint32_t id;
143
144 if (argc < 4 || argc > 5)
145 return usage(argv[0]);
146
147 blob_buf_init(&b, 0);
148 if (argc == 5 && !blobmsg_add_json_from_string(&b, argv[4])) {
149 fprintf(stderr, "Failed to parse message data\n");
150 goto out;
151 }
152
153 ret = ubus_lookup_id(ctx, argv[2], &id);
154 if (!ret)
155 ret = ubus_invoke(ctx, id, argv[3], b.head, receive_data, NULL);
156 } else if (!strcmp(cmd, "listen")) {
157 ret = ubus_cli_listen(ctx, argc - 2, argv + 2);
158 } else {
159 return usage(argv[0]);
160 }
161
162 if (ret)
163 fprintf(stderr, "Failed: %s\n", ubus_strerror(ret));
164
165 out:
166 ubus_free(ctx);
167 return ret;
168 }