+static
+void add_to_loaded_plugins(struct bt_plugin **plugins)
+{
+ while (*plugins) {
+ struct bt_plugin *plugin = *plugins;
+ /* Check if it's already loaded (from another path). */
+ struct bt_plugin *loaded_plugin =
+ find_plugin(bt_plugin_get_name(plugin));
+
+ if (loaded_plugin) {
+ printf_verbose("Not loading plugin `%s`: already loaded from `%s`\n",
+ bt_plugin_get_path(plugin),
+ bt_plugin_get_path(loaded_plugin));
+ BT_PUT(loaded_plugin);
+ BT_PUT(plugin);
+ } else {
+ /* Transfer ownership to global array. */
+ g_ptr_array_add(loaded_plugins, plugin);
+ }
+ *(plugins++) = NULL;
+ }
+}
+
+static
+int load_dynamic_plugins(struct bt_value *plugin_paths)
+{
+ int nr_paths, i, ret = 0;
+
+ nr_paths = bt_value_array_size(plugin_paths);
+ if (nr_paths < 0) {
+ ret = -1;
+ goto end;
+ }
+
+ for (i = 0; i < nr_paths; i++) {
+ struct bt_value *plugin_path_value = NULL;
+ const char *plugin_path;
+ struct bt_plugin **plugins;
+
+ plugin_path_value = bt_value_array_get(plugin_paths, i);
+ if (bt_value_string_get(plugin_path_value,
+ &plugin_path)) {
+ BT_PUT(plugin_path_value);
+ continue;
+ }
+
+ plugins = bt_plugin_create_all_from_dir(plugin_path, false);
+ if (!plugins) {
+ printf_debug("Unable to dynamically load plugins from path %s.\n",
+ plugin_path);
+ BT_PUT(plugin_path_value);
+ continue;
+ }
+
+ add_to_loaded_plugins(plugins);
+ free(plugins);
+
+ BT_PUT(plugin_path_value);
+ }
+end:
+ return ret;
+}
+
+static
+int load_static_plugins(void)
+{
+ int ret = 0;
+ struct bt_plugin **plugins;
+
+ plugins = bt_plugin_create_all_from_static();
+ if (!plugins) {
+ printf_debug("Unable to load static plugins.\n");
+ ret = -1;
+ goto end;
+ }
+
+ add_to_loaded_plugins(plugins);
+ free(plugins);
+end:
+ return ret;
+}
+
+static int load_all_plugins(struct bt_value *plugin_paths)
+{
+ int ret = 0;
+
+ if (load_dynamic_plugins(plugin_paths)) {
+ fprintf(stderr, "Failed to load dynamic plugins.\n");
+ ret = -1;
+ goto end;
+ }
+
+ if (load_static_plugins()) {
+ fprintf(stderr, "Failed to load static plugins.\n");
+ ret = -1;
+ goto end;
+ }
+
+end:
+ return ret;
+}
+
+static void print_plugin_info(struct bt_plugin *plugin)
+{
+ unsigned int major, minor, patch;
+ const char *extra;
+ enum bt_plugin_status version_status;
+ const char *plugin_name;
+ const char *path;
+ const char *author;
+ const char *license;
+ const char *plugin_description;
+
+ plugin_name = bt_plugin_get_name(plugin);
+ path = bt_plugin_get_path(plugin);
+ author = bt_plugin_get_author(plugin);
+ license = bt_plugin_get_license(plugin);
+ plugin_description = bt_plugin_get_description(plugin);
+ version_status = bt_plugin_get_version(plugin, &major, &minor,
+ &patch, &extra);
+ printf("%s%s%s%s:\n", bt_common_color_bold(),
+ bt_common_color_fg_blue(), plugin_name,
+ bt_common_color_reset());
+ printf(" %sPath%s: %s\n", bt_common_color_bold(),
+ bt_common_color_reset(), path ? path : "(None)");
+
+ if (version_status == BT_PLUGIN_STATUS_OK) {
+ printf(" %sVersion%s: %u.%u.%u",
+ bt_common_color_bold(), bt_common_color_reset(),
+ major, minor, patch);
+
+ if (extra) {
+ printf("%s", extra);
+ }
+
+ printf("\n");
+ }
+
+ printf(" %sDescription%s: %s\n", bt_common_color_bold(),
+ bt_common_color_reset(),
+ plugin_description ? plugin_description : "(None)");
+ printf(" %sAuthor%s: %s\n", bt_common_color_bold(),
+ bt_common_color_reset(), author ? author : "(Unknown)");
+ printf(" %sLicense%s: %s\n", bt_common_color_bold(),
+ bt_common_color_reset(),
+ license ? license : "(Unknown)");
+}
+
+static int cmd_query(struct bt_config *cfg)