1a49495c11a0b75d6b6a9134e553dcb765bd7683
[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 }