+static void uh_ubus_list_cb(struct ubus_context *ctx, struct ubus_object_data *obj, void *priv)
+{
+ struct blob_attr *sig, *attr;
+ int rem, rem2;
+ void *t, *o;
+
+ if (!priv) {
+ blobmsg_add_string(&buf, NULL, obj->path);
+ return;
+ }
+
+ if (!obj->signature)
+ return;
+
+ o = blobmsg_open_table(&buf, obj->path);
+ blob_for_each_attr(sig, obj->signature, rem) {
+ t = blobmsg_open_table(&buf, blobmsg_name(sig));
+ rem2 = blobmsg_data_len(sig);
+ __blob_for_each_attr(attr, blobmsg_data(sig), rem2) {
+ if (blob_id(attr) != BLOBMSG_TYPE_INT32)
+ continue;
+
+ switch (blobmsg_get_u32(attr)) {
+ case BLOBMSG_TYPE_INT8:
+ blobmsg_add_string(&buf, blobmsg_name(attr), "boolean");
+ break;
+ case BLOBMSG_TYPE_INT32:
+ blobmsg_add_string(&buf, blobmsg_name(attr), "number");
+ break;
+ case BLOBMSG_TYPE_STRING:
+ blobmsg_add_string(&buf, blobmsg_name(attr), "string");
+ break;
+ case BLOBMSG_TYPE_ARRAY:
+ blobmsg_add_string(&buf, blobmsg_name(attr), "array");
+ break;
+ case BLOBMSG_TYPE_TABLE:
+ blobmsg_add_string(&buf, blobmsg_name(attr), "object");
+ break;
+ default:
+ blobmsg_add_string(&buf, blobmsg_name(attr), "unknown");
+ break;
+ }
+ }
+ blobmsg_close_table(&buf, t);
+ }
+ blobmsg_close_table(&buf, o);
+}
+
+static void uh_ubus_send_list(struct client *cl, json_object *obj, struct blob_attr *params)
+{
+ struct blob_attr *cur, *dup;
+ void *r;
+ int rem;
+
+ uh_ubus_init_response(cl);
+
+ if (!params || blob_id(params) != BLOBMSG_TYPE_ARRAY) {
+ r = blobmsg_open_array(&buf, "result");
+ ubus_lookup(ctx, NULL, uh_ubus_list_cb, NULL);
+ blobmsg_close_array(&buf, r);
+ }
+ else {
+ r = blobmsg_open_table(&buf, "result");
+ dup = blob_memdup(params);
+ if (dup)
+ {
+ rem = blobmsg_data_len(dup);
+ __blob_for_each_attr(cur, blobmsg_data(dup), rem)
+ ubus_lookup(ctx, blobmsg_data(cur), uh_ubus_list_cb, blobmsg_data(cur));
+ free(dup);
+ }
+ blobmsg_close_table(&buf, r);
+ }
+
+ uh_ubus_send_response(cl);
+}
+