Add bt_plugin_create_from_name()
[babeltrace.git] / converter / babeltrace-cfg.c
index 804b73390ac745b83e45cb63b17728e55e7bfc8f..608b65484df49c06490a7c3ea23795607a9650a3 100644 (file)
 #include <stdbool.h>
 #include <inttypes.h>
 #include <babeltrace/babeltrace.h>
+#include <babeltrace/common-internal.h>
 #include <babeltrace/values.h>
 #include <popt.h>
 #include <glib.h>
+#include <sys/types.h>
+#include <pwd.h>
 #include "babeltrace-cfg.h"
 
 #define DEFAULT_SOURCE_COMPONENT_NAME  "ctf.fs"
+#define DEFAULT_SINK_COMPONENT_NAME    "text.text"
 
 /*
  * Error printf() macro which prepends "Error: " the first time it's
@@ -782,6 +786,8 @@ void print_usage(FILE *fp)
        fprintf(fp, "      --begin                       Start time: [YYYY-MM-DD [hh:mm:]]ss[.nnnnnnnnn]\n");
        fprintf(fp, "      --end                         End time: [YYYY-MM-DD [hh:mm:]]ss[.nnnnnnnnn]\n");
        fprintf(fp, "      --timerange                   Time range: begin,end or [begin,end] (where [] are actual brackets)\n");
+       fprintf(fp, "      --omit-system-plugin-path     Omit system plugins from plugin search path\n");
+       fprintf(fp, "      --omit-home-plugin-path       Omit home plugins from plugin search path\n");
        fprintf(fp, "  -h  --help                        Show this help\n");
        fprintf(fp, "      --help-legacy                 Show Babeltrace 1.x legacy options\n");
        fprintf(fp, "  -v, --verbose                     Enable verbose output\n");
@@ -956,6 +962,17 @@ end:
        return;
 }
 
+static
+bool is_setuid_setgid(void)
+{
+       return (geteuid() != getuid() || getegid() != getgid());
+}
+
+static void destroy_gstring(void *data)
+{
+       g_string_free(data, TRUE);
+}
+
 /*
  * Extracts the various paths from the string arg, delimited by ':',
  * and converts them to an array value object.
@@ -965,59 +982,34 @@ end:
  * Return value is owned by the caller.
  */
 static
-struct bt_value *plugin_paths_from_arg(const char *arg)
+enum bt_value_status plugin_paths_from_arg(struct bt_value *plugin_paths,
+               const char *arg)
 {
-       struct bt_value *plugin_paths;
-       const char *at = arg;
-       const char *end = arg + strlen(arg);
+       enum bt_value_status status = BT_VALUE_STATUS_OK;
+       GPtrArray *dirs = g_ptr_array_new_with_free_func(destroy_gstring);
+       int ret;
+       size_t i;
 
-       plugin_paths = bt_value_array_create();
-       if (!plugin_paths) {
-               print_err_oom();
-               goto error;
+       if (!dirs) {
+               status = BT_VALUE_STATUS_ERROR;
+               goto end;
        }
 
-       while (at < end) {
-               int ret;
-               GString *path;
-               const char *next_colon;
-
-               next_colon = strchr(at, ':');
-               if (next_colon == at) {
-                       /*
-                        * Empty path: try next character (supported
-                        * to conform to the typical parsing of $PATH).
-                        */
-                       at++;
-                       continue;
-               } else if (!next_colon) {
-                       /* No more colon: use the remaining */
-                       next_colon = arg + strlen(arg);
-               }
-
-               path = g_string_new(NULL);
-               if (!path) {
-                       print_err_oom();
-                       goto error;
-               }
-
-               g_string_append_len(path, at, next_colon - at);
-               at = next_colon + 1;
-               ret = bt_value_array_append_string(plugin_paths, path->str);
-               g_string_free(path, TRUE);
-               if (ret) {
-                       print_err_oom();
-                       goto error;
-               }
+       ret = bt_common_append_plugin_path_dirs(arg, dirs);
+       if (ret) {
+               status = BT_VALUE_STATUS_ERROR;
+               goto end;
        }
 
-       goto end;
+       for (i = 0; i < dirs->len; i++) {
+               GString *dir = g_ptr_array_index(dirs, i);
 
-error:
-       BT_PUT(plugin_paths);
+               bt_value_array_append_string(plugin_paths, dir->str);
+       }
 
 end:
-       return plugin_paths;
+       g_ptr_array_free(dirs, TRUE);
+       return status;
 }
 
 /*
@@ -2005,14 +1997,12 @@ bool validate_cfg(struct bt_config *cfg,
 
        /* Determine if the input and output should be legacy-style */
        if (*legacy_input_format != LEGACY_INPUT_FORMAT_NONE ||
-                       cfg->sources->len == 0 ||
                        !bt_value_array_is_empty(legacy_input_paths) ||
                        ctf_legacy_opts_is_any_set(ctf_legacy_opts)) {
                legacy_input = true;
        }
 
        if (*legacy_output_format != LEGACY_OUTPUT_FORMAT_NONE ||
-                       cfg->sinks->len == 0 ||
                        text_legacy_opts_is_any_set(text_legacy_opts)) {
                legacy_output = true;
        }
@@ -2145,6 +2135,8 @@ enum {
        OPT_TIMERANGE,
        OPT_VERBOSE,
        OPT_VERSION,
+       OPT_OMIT_SYSTEM_PLUGIN_PATH,
+       OPT_OMIT_HOME_PLUGIN_PATH,
 };
 
 /* popt long option descriptions */
@@ -2183,6 +2175,8 @@ static struct poptOption long_options[] = {
        { "timerange", '\0', POPT_ARG_STRING, NULL, OPT_TIMERANGE, NULL, NULL },
        { "verbose", 'v', POPT_ARG_NONE, NULL, OPT_VERBOSE, NULL, NULL },
        { "version", 'V', POPT_ARG_NONE, NULL, OPT_VERSION, NULL, NULL },
+       { "omit-system-plugin-path", '\0', POPT_ARG_NONE, NULL, OPT_OMIT_SYSTEM_PLUGIN_PATH, NULL, NULL },
+       { "omit-home-plugin-path", '\0', POPT_ARG_NONE, NULL, OPT_OMIT_HOME_PLUGIN_PATH, NULL, NULL },
        { NULL, 0, 0, NULL, 0, NULL, NULL },
 };
 
@@ -2248,26 +2242,118 @@ not_found:
        return -1;
 }
 
+static int add_internal_plugin_paths(struct bt_config *cfg)
+{
+       int ret;
+
+       if (!cfg->omit_home_plugin_path) {
+               if (bt_common_is_setuid_setgid()) {
+                       printf_debug("Skipping non-system plugin paths for setuid/setgid binary.");
+               } else {
+                       char *home_plugin_dir =
+                               bt_common_get_home_plugin_path();
+
+                       if (home_plugin_dir) {
+                               ret = plugin_paths_from_arg(cfg->plugin_paths,
+                                       home_plugin_dir);
+                               free(home_plugin_dir);
+
+                               if (ret) {
+                                       printf_err("Invalid home plugin path\n");
+                                       goto error;
+                               }
+                       }
+               }
+       }
+
+       if (!cfg->omit_system_plugin_path) {
+               if (plugin_paths_from_arg(cfg->plugin_paths,
+                               bt_common_get_system_plugin_path())) {
+                       printf_err("Invalid system plugin path\n");
+                       goto error;
+               }
+       }
+       return 0;
+error:
+       return -1;
+}
+
+static int append_sources_from_implicit_params(GPtrArray *sources,
+               struct bt_config_component *implicit_source_comp)
+{
+       size_t i;
+       size_t len = sources->len;
+
+       for (i = 0; i < len; i++) {
+               struct bt_config_component *comp;
+               struct bt_value *params_to_set;
+
+               comp = g_ptr_array_index(sources, i);
+               params_to_set = bt_value_map_extend(comp->params,
+                       implicit_source_comp->params);
+               if (!params_to_set) {
+                       printf_err("Cannot extend legacy component parameters with non-legacy parameters\n");
+                       goto error;
+               }
+               BT_MOVE(comp->params, params_to_set);
+       }
+       return 0;
+error:
+       return -1;
+}
+
+struct bt_config *bt_config_create(void)
+{
+       struct bt_config *cfg;
+
+       /* Create config */
+       cfg = g_new0(struct bt_config, 1);
+       if (!cfg) {
+               print_err_oom();
+               goto error;
+       }
+
+       bt_object_init(cfg, bt_config_destroy);
+       cfg->sources = g_ptr_array_new_with_free_func((GDestroyNotify) bt_put);
+       if (!cfg->sources) {
+               print_err_oom();
+               goto error;
+       }
+
+       cfg->sinks = g_ptr_array_new_with_free_func((GDestroyNotify) bt_put);
+       if (!cfg->sinks) {
+               print_err_oom();
+               goto error;
+       }
+
+       cfg->plugin_paths = bt_value_array_create();
+       if (!cfg->plugin_paths) {
+               print_err_oom();
+               goto error;
+       }
+end:
+       return cfg;
+error:
+       BT_PUT(cfg);
+       goto end;
+}
+
 /*
  * Returns a Babeltrace configuration, out of command-line arguments,
  * containing everything that is needed to instanciate specific
  * components with given parameters.
  *
- * *exit_code is set to the appropriate exit code to use as far as this
- * function goes.
- *
- * Return value is NULL on error, otherwise it's owned by the caller.
+ * Return value is set to the appropriate exit code to use.
  */
-struct bt_config *bt_config_from_args(int argc, const char *argv[], int *exit_code)
+int bt_config_init_from_args(struct bt_config *cfg, int argc, const char *argv[])
 {
-       struct bt_config *cfg = NULL;
        poptContext pc = NULL;
        char *arg = NULL;
        struct ctf_legacy_opts ctf_legacy_opts;
        struct text_legacy_opts text_legacy_opts;
        enum legacy_input_format legacy_input_format = LEGACY_INPUT_FORMAT_NONE;
        enum legacy_output_format legacy_output_format =
-               LEGACY_OUTPUT_FORMAT_NONE;
+                       LEGACY_OUTPUT_FORMAT_NONE;
        struct bt_value *legacy_input_paths = NULL;
        struct bt_config_component *implicit_source_comp = NULL;
        struct bt_config_component *cur_cfg_comp = NULL;
@@ -2276,17 +2362,10 @@ struct bt_config *bt_config_from_args(int argc, const char *argv[], int *exit_co
        enum bt_config_component_dest cur_cfg_comp_dest =
                BT_CONFIG_COMPONENT_DEST_SOURCE;
        struct bt_value *cur_base_params = NULL;
-       int opt;
-       bool cur_cfg_comp_params_set = false;
+       int opt, ret = 0;
 
        memset(&ctf_legacy_opts, 0, sizeof(ctf_legacy_opts));
        memset(&text_legacy_opts, 0, sizeof(text_legacy_opts));
-       *exit_code = 0;
-
-       if (argc <= 1) {
-               print_usage(stdout);
-               goto end;
-       }
 
        text_legacy_opts.output = g_string_new(NULL);
        if (!text_legacy_opts.output) {
@@ -2312,26 +2391,6 @@ struct bt_config *bt_config_from_args(int argc, const char *argv[], int *exit_co
                goto error;
        }
 
-       /* Create config */
-       cfg = g_new0(struct bt_config, 1);
-       if (!cfg) {
-               print_err_oom();
-               goto error;
-       }
-
-       bt_object_init(cfg, bt_config_destroy);
-       cfg->sources = g_ptr_array_new_with_free_func((GDestroyNotify) bt_put);
-       if (!cfg->sources) {
-               print_err_oom();
-               goto error;
-       }
-
-       cfg->sinks = g_ptr_array_new_with_free_func((GDestroyNotify) bt_put);
-       if (!cfg->sinks) {
-               print_err_oom();
-               goto error;
-       }
-
        legacy_input_paths = bt_value_array_create();
        if (!legacy_input_paths) {
                print_err_oom();
@@ -2363,17 +2422,21 @@ struct bt_config *bt_config_from_args(int argc, const char *argv[], int *exit_co
 
                switch (opt) {
                case OPT_PLUGIN_PATH:
-                       if (cfg->plugin_paths) {
-                               printf_err("Duplicate --plugin-path option\n");
-                               goto error;
-                       }
-
-                       cfg->plugin_paths = plugin_paths_from_arg(arg);
-                       if (!cfg->plugin_paths) {
-                               printf_err("Invalid --plugin-path option's argument\n");
-                               goto error;
+                       if (is_setuid_setgid()) {
+                               printf_debug("Skipping non-system plugin paths for setuid/setgid binary.");
+                       } else {
+                               if (plugin_paths_from_arg(cfg->plugin_paths, arg)) {
+                                       printf_err("Invalid --plugin-path option's argument\n");
+                                       goto error;
+                               }
                        }
                        break;
+               case OPT_OMIT_SYSTEM_PLUGIN_PATH:
+                       cfg->omit_system_plugin_path = true;
+                       break;
+               case OPT_OMIT_HOME_PLUGIN_PATH:
+                       cfg->omit_home_plugin_path = true;
+                       break;
                case OPT_OUTPUT_PATH:
                        if (text_legacy_opts.output->len > 0) {
                                printf_err("Duplicate --output option\n");
@@ -2444,13 +2507,12 @@ struct bt_config *bt_config_from_args(int argc, const char *argv[], int *exit_co
                        assert(cur_base_params);
                        bt_put(cur_cfg_comp->params);
                        cur_cfg_comp->params = bt_value_copy(cur_base_params);
-                       if (!cur_cfg_comp) {
+                       if (!cur_cfg_comp->params) {
                                print_err_oom();
                                goto end;
                        }
 
                        cur_cfg_comp_dest = BT_CONFIG_COMPONENT_DEST_SOURCE;
-                       cur_cfg_comp_params_set = false;
                        break;
                }
                case OPT_OUTPUT_FORMAT:
@@ -2507,13 +2569,12 @@ struct bt_config *bt_config_from_args(int argc, const char *argv[], int *exit_co
                        assert(cur_base_params);
                        bt_put(cur_cfg_comp->params);
                        cur_cfg_comp->params = bt_value_copy(cur_base_params);
-                       if (!cur_cfg_comp) {
+                       if (!cur_cfg_comp->params) {
                                print_err_oom();
                                goto end;
                        }
 
                        cur_cfg_comp_dest = BT_CONFIG_COMPONENT_DEST_SINK;
-                       cur_cfg_comp_params_set = false;
                        break;
                }
                case OPT_PARAMS:
@@ -2527,13 +2588,6 @@ struct bt_config *bt_config_from_args(int argc, const char *argv[], int *exit_co
                                goto error;
                        }
 
-                       if (cur_cfg_comp_params_set) {
-                               printf_err("Duplicate --params option for the same current component\ninstance (class %s.%s)\n",
-                                       cur_cfg_comp->plugin_name->str,
-                                       cur_cfg_comp->component_name->str);
-                               goto error;
-                       }
-
                        params = bt_value_from_arg(arg);
                        if (!params) {
                                printf_err("Invalid format for --params option's argument:\n    %s\n",
@@ -2541,17 +2595,16 @@ struct bt_config *bt_config_from_args(int argc, const char *argv[], int *exit_co
                                goto error;
                        }
 
-                       params_to_set = bt_value_map_extend(cur_base_params,
+                       params_to_set = bt_value_map_extend(cur_cfg_comp->params,
                                params);
                        BT_PUT(params);
                        if (!params_to_set) {
-                               printf_err("Cannot extend current base parameters with --params option's argument:\n    %s\n",
+                               printf_err("Cannot extend current component parameters with --params option's argument:\n    %s\n",
                                        arg);
                                goto error;
                        }
 
                        BT_MOVE(cur_cfg_comp->params, params_to_set);
-                       cur_cfg_comp_params_set = true;
                        break;
                }
                case OPT_PATH:
@@ -2734,15 +2787,12 @@ struct bt_config *bt_config_from_args(int argc, const char *argv[], int *exit_co
                        break;
                }
                case OPT_HELP:
-                       BT_PUT(cfg);
                        print_usage(stdout);
                        goto end;
                case OPT_HELP_LEGACY:
-                       BT_PUT(cfg);
                        print_legacy_usage(stdout);
                        goto end;
                case OPT_VERSION:
-                       BT_PUT(cfg);
                        print_version();
                        goto end;
                case OPT_LIST:
@@ -2764,22 +2814,9 @@ struct bt_config *bt_config_from_args(int argc, const char *argv[], int *exit_co
                arg = NULL;
        }
 
-       /* Append current component configuration, if any */
-       if (cur_cfg_comp && !cur_is_implicit_source) {
-               add_cfg_comp(cfg, cur_cfg_comp, cur_cfg_comp_dest);
-       }
-       cur_cfg_comp = NULL;
-
-       if (use_implicit_source) {
-               add_cfg_comp(cfg, implicit_source_comp,
-                       BT_CONFIG_COMPONENT_DEST_SOURCE);
-               implicit_source_comp = NULL;
-       } else {
-               if (implicit_source_comp
-                               && !bt_value_map_is_empty(implicit_source_comp->params)) {
-                       printf_err("Arguments specified for implicit source, but an explicit source has been specified, overriding it\n");
-                       goto error;
-               }
+       if (argc <= 1) {
+               print_usage(stdout);
+               goto end;
        }
 
        /* Check for option parsing error */
@@ -2804,6 +2841,16 @@ struct bt_config *bt_config_from_args(int argc, const char *argv[], int *exit_co
                }
        }
 
+       if (add_internal_plugin_paths(cfg)) {
+               goto error;
+       }
+
+       /* Append current component configuration, if any */
+       if (cur_cfg_comp && !cur_is_implicit_source) {
+               add_cfg_comp(cfg, cur_cfg_comp, cur_cfg_comp_dest);
+       }
+       cur_cfg_comp = NULL;
+
        /* Validate legacy/non-legacy options */
        if (!validate_cfg(cfg, &legacy_input_format, &legacy_output_format,
                        legacy_input_paths, &ctf_legacy_opts,
@@ -2823,6 +2870,24 @@ struct bt_config *bt_config_from_args(int argc, const char *argv[], int *exit_co
                        printf_err("Cannot convert legacy input format options to source component instance(s)\n");
                        goto error;
                }
+               if (append_sources_from_implicit_params(cfg->sources,
+                               implicit_source_comp)) {
+                       printf_err("Cannot initialize legacy component parameters\n");
+                       goto error;
+               }
+               use_implicit_source = false;
+       } else {
+               if (use_implicit_source) {
+                       add_cfg_comp(cfg, implicit_source_comp,
+                               BT_CONFIG_COMPONENT_DEST_SOURCE);
+                       implicit_source_comp = NULL;
+               } else {
+                       if (implicit_source_comp
+                                       && !bt_value_map_is_empty(implicit_source_comp->params)) {
+                               printf_err("Arguments specified for implicit source, but an explicit source has been specified, overriding it\n");
+                               goto error;
+                       }
+               }
        }
 
        /*
@@ -2837,13 +2902,22 @@ struct bt_config *bt_config_from_args(int argc, const char *argv[], int *exit_co
                }
        }
 
+       if (cfg->sinks->len == 0) {
+               /* Use implicit sink as default. */
+               cur_cfg_comp = bt_config_component_from_arg(DEFAULT_SINK_COMPONENT_NAME);
+               if (!cur_cfg_comp) {
+                       printf_error("Cannot find implicit sink plugin \"%s\"\n",
+                               DEFAULT_SINK_COMPONENT_NAME);
+               }
+               add_cfg_comp(cfg, cur_cfg_comp,
+                       BT_CONFIG_COMPONENT_DEST_SINK);
+               cur_cfg_comp = NULL;
+       }
+
        goto end;
 
 error:
-       BT_PUT(cfg);
-       cfg = NULL;
-       *exit_code = 1;
-
+       ret = 1;
 end:
        if (pc) {
                poptFreeContext(pc);
@@ -2868,5 +2942,5 @@ end:
        BT_PUT(text_legacy_opts.names);
        BT_PUT(text_legacy_opts.fields);
        BT_PUT(legacy_input_paths);
-       return cfg;
+       return ret;
 }
This page took 0.029374 seconds and 4 git commands to generate.