Make babeltrace(1)'s CLI Git-like and implement the list-plugins command
[babeltrace.git] / converter / babeltrace-cfg.c
index f045bf94e973b6c4c16ef989b64cb4e516d8eff9..1d4e7537394f1933acf2590310d6ea738b1a2de9 100644 (file)
@@ -691,143 +691,6 @@ void print_version(void)
        puts("Babeltrace " VERSION);
 }
 
-/*
- * Prints the legacy, Babeltrace 1.x command usage. Those options are
- * still compatible in Babeltrace 2.x, but it is recommended to use
- * the more generic plugin/component parameters instead of those
- * hard-coded option names.
- */
-static
-void print_legacy_usage(FILE *fp)
-{
-       fprintf(fp, "Usage: babeltrace [OPTIONS] INPUT...\n");
-       fprintf(fp, "\n");
-       fprintf(fp, "The following options are compatible with the Babeltrace 1.x options:\n");
-       fprintf(fp, "\n");
-       fprintf(fp, "      --help-legacy            Show this help\n");
-       fprintf(fp, "  -V, --version                Show version\n");
-       fprintf(fp, "      --clock-force-correlate  Assume that clocks are inherently correlated\n");
-       fprintf(fp, "                               across traces\n");
-       fprintf(fp, "  -d, --debug                  Enable debug mode\n");
-       fprintf(fp, "  -i, --input-format=FORMAT    Input trace format (default: ctf)\n");
-       fprintf(fp, "  -l, --list                   List available formats\n");
-       fprintf(fp, "  -o, --output-format=FORMAT   Output trace format (default: text)\n");
-       fprintf(fp, "  -v, --verbose                Enable verbose output\n");
-       fprintf(fp, "\n");
-       fprintf(fp, "  Available input formats:  ctf, lttng-live, ctf-metadata\n");
-       fprintf(fp, "  Available output formats: text, dummy\n");
-       fprintf(fp, "\n");
-       fprintf(fp, "Input formats specific options:\n");
-       fprintf(fp, "\n");
-       fprintf(fp, "  INPUT...                     Input trace file(s), directory(ies), or URLs\n");
-       fprintf(fp, "      --clock-offset=SEC       Set clock offset to SEC seconds\n");
-       fprintf(fp, "      --clock-offset-ns=NS     Set clock offset to NS nanoseconds\n");
-       fprintf(fp, "      --stream-intersection    Only process events when all streams are active\n");
-       fprintf(fp, "\n");
-       fprintf(fp, "text output format specific options:\n");
-       fprintf(fp, "  \n");
-       fprintf(fp, "      --clock-cycles           Print timestamps in clock cycles\n");
-       fprintf(fp, "      --clock-date             Print timestamp dates\n");
-       fprintf(fp, "      --clock-gmt              Print and parse timestamps in GMT time zone\n");
-       fprintf(fp, "                               (default: local time zone)\n");
-       fprintf(fp, "      --clock-seconds          Print the timestamps as [SEC.NS]\n");
-       fprintf(fp, "                               (default format: [HH:MM:SS.NS])\n");
-       fprintf(fp, "      --debug-info-dir=DIR     Search for debug info in directory DIR\n");
-       fprintf(fp, "                               (default: `/usr/lib/debug`)\n");
-       fprintf(fp, "      --debug-info-full-path   Show full debug info source and binary paths\n");
-       fprintf(fp, "      --debug-info-target-prefix=DIR  Use directory DIR as a prefix when looking\n");
-       fprintf(fp, "                                      up executables during debug info analysis\n");
-       fprintf(fp, "                               (default: `/usr/lib/debug`)\n");
-       fprintf(fp, "  -f, --fields=NAME[,NAME]...  Print additional fields:\n");
-       fprintf(fp, "                                 all, trace, trace:hostname, trace:domain,\n");
-       fprintf(fp, "                                 trace:procname, trace:vpid, loglevel, emf\n");
-       fprintf(fp, "                                 (default: trace:hostname, trace:procname,\n");
-       fprintf(fp, "                                           trace:vpid)\n");
-       fprintf(fp, "  -n, --names=NAME[,NAME]...   Print field names:\n");
-       fprintf(fp, "                                 payload (or arg or args)\n");
-       fprintf(fp, "                                 none, all, scope, header, context (or ctx)\n");
-       fprintf(fp, "                                 (default: payload, context)\n");
-       fprintf(fp, "      --no-delta               Do not print time delta between consecutive\n");
-       fprintf(fp, "                               events\n");
-       fprintf(fp, "  -w, --output=PATH            Write output to PATH (default: standard output)\n");
-}
-
-/*
- * Prints the Babeltrace 2.x usage.
- */
-static
-void print_usage(FILE *fp)
-{
-       fprintf(fp, "Usage: babeltrace [OPTIONS]\n");
-       fprintf(fp, "\n");
-       fprintf(fp, "  -b, --base-params=PARAMS          Set PARAMS as the current base parameters\n");
-       fprintf(fp, "                                    of the following source and sink component\n");
-       fprintf(fp, "                                    instances (see the exact format of PARAMS\n");
-       fprintf(fp, "                                    below)\n");
-       fprintf(fp, "      --begin=BEGIN                 Set beginning time to BEGIN\n");
-       fprintf(fp, "                                    (format: [YYYY-MM-DD [hh:mm:]]ss[.nnnnnnnnn])\n");
-       fprintf(fp, "  -d, --debug                       Enable debug mode\n");
-       fprintf(fp, "      --end=END                     Set end time to END\n");
-       fprintf(fp, "                                    (format: [YYYY-MM-DD [hh:mm:]]ss[.nnnnnnnnn])\n");
-       fprintf(fp, "  -l, --list                        List available plugins and their components\n");
-       fprintf(fp, "      --omit-home-plugin-path       Omit home plugins from plugin search path\n");
-       fprintf(fp, "                                    (~/.local/lib/babeltrace/plugins)\n");
-       fprintf(fp, "      --omit-system-plugin-path     Omit system plugins from plugin search path\n");
-       fprintf(fp, "  -p, --params=PARAMS               Set the parameters of the latest source or\n");
-       fprintf(fp, "                                    sink component instance (in command-line \n");
-       fprintf(fp, "                                    order) to PARAMS (see the exact format of\n");
-       fprintf(fp, "                                    PARAMS below)\n");
-       fprintf(fp, "  -P, --path=PATH                   Set the `path` parameter of the latest source\n");
-       fprintf(fp, "                                    or sink component to PATH\n");
-       fprintf(fp, "      --plugin-path=PATH[:PATH]...  Add PATH to the list of paths from which dynamic\n");
-       fprintf(fp, "                                    plugins can be loaded\n");
-       fprintf(fp, "  -r, --reset-base-params           Reset the current base parameters of the\n");
-       fprintf(fp, "                                    following source and sink component\n");
-       fprintf(fp, "                                    instances to an empty map\n");
-       fprintf(fp, "  -o, --sink=PLUGIN.COMPCLS         Instantiate a sink component from plugin\n");
-       fprintf(fp, "                                    PLUGIN and component class COMPCLS (may be\n");
-       fprintf(fp, "                                    repeated)\n");
-       fprintf(fp, "  -i, --source=PLUGIN.COMPCLS       Instantiate a source component from plugin\n");
-       fprintf(fp, "                                    PLUGIN and component class COMPCLS (may be\n");
-       fprintf(fp, "                                    repeated)\n");
-       fprintf(fp, "      --timerange=TIMERANGE         Set time range to TIMERANGE: BEGIN,END or\n");
-       fprintf(fp, "                                    [BEGIN,END] (where [ and ] are actual brackets)\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");
-       fprintf(fp, "  -V, --version                     Show version\n");
-       fprintf(fp, "\n\n");
-       fprintf(fp, "Format of PARAMS\n");
-       fprintf(fp, "----------------\n");
-       fprintf(fp, "\n");
-       fprintf(fp, "    PARAM=VALUE[,PARAM=VALUE]...\n");
-       fprintf(fp, "\n");
-       fprintf(fp, "The parameter string is a comma-separated list of PARAM=VALUE assignments,\n");
-       fprintf(fp, "where PARAM is the parameter name (C identifier plus [:.-] characters), and\n");
-       fprintf(fp, "VALUE can be one of:\n");
-       fprintf(fp, "\n");
-       fprintf(fp, "* `null`, `nul`, `NULL`: null value (no backticks).\n");
-       fprintf(fp, "* `true`, `TRUE`, `yes`, `YES`: true boolean value (no backticks).\n");
-       fprintf(fp, "* `false`, `FALSE`, `no`, `NO`: false boolean value (no backticks).\n");
-       fprintf(fp, "* Binary (`0b` prefix), octal (`0` prefix), decimal, or hexadecimal\n");
-       fprintf(fp, "  (`0x` prefix) signed 64-bit integer.\n");
-       fprintf(fp, "* Double precision floating point number (scientific notation is accepted).\n");
-       fprintf(fp, "* Unquoted string with no special characters, and not matching any of\n");
-       fprintf(fp, "  the null and boolean value symbols above.\n");
-       fprintf(fp, "* Double-quoted string (accepts escape characters).\n");
-       fprintf(fp, "\n");
-       fprintf(fp, "Whitespaces are allowed around individual `=` and `,` tokens.\n");
-       fprintf(fp, "\n");
-       fprintf(fp, "Example:\n");
-       fprintf(fp, "\n");
-       fprintf(fp, "    many=null, fresh=yes, condition=false, squirrel=-782329,\n");
-       fprintf(fp, "    observe=3.14, simple=beef, needs-quotes=\"some string\",\n");
-       fprintf(fp, "    escape.chars-are:allowed=\"this is a \\\" double quote\"\n");
-       fprintf(fp, "\n");
-       fprintf(fp, "IMPORTANT: Make sure to single-quote the whole argument when you run babeltrace\n");
-       fprintf(fp, "from a shell.\n");
-}
-
 /*
  * Destroys a component configuration.
  */
@@ -944,23 +807,35 @@ end:
 static
 void bt_config_destroy(struct bt_object *obj)
 {
-       struct bt_config *bt_config =
+       struct bt_config *cfg =
                container_of(obj, struct bt_config, base);
 
        if (!obj) {
                goto end;
        }
 
-       if (bt_config->sources) {
-               g_ptr_array_free(bt_config->sources, TRUE);
-       }
+       switch (cfg->command) {
+       case BT_CONFIG_COMMAND_CONVERT:
+               if (cfg->cmd_data.convert.sources) {
+                       g_ptr_array_free(cfg->cmd_data.convert.sources, TRUE);
+               }
 
-       if (bt_config->sinks) {
-               g_ptr_array_free(bt_config->sinks, TRUE);
+               if (cfg->cmd_data.convert.sinks) {
+                       g_ptr_array_free(cfg->cmd_data.convert.sinks, TRUE);
+               }
+
+               BT_PUT(cfg->cmd_data.convert.plugin_paths);
+               break;
+
+       case BT_CONFIG_COMMAND_LIST_PLUGINS:
+               BT_PUT(cfg->cmd_data.list_plugins.plugin_paths);
+               break;
+
+       default:
+               assert(false);
        }
 
-       BT_PUT(bt_config->plugin_paths);
-       g_free(bt_config);
+       g_free(cfg);
 
 end:
        return;
@@ -2022,7 +1897,7 @@ bool validate_cfg(struct bt_config *cfg,
                }
 
                /* Make sure no non-legacy sources are specified */
-               if (cfg->sources->len != 0) {
+               if (cfg->cmd_data.convert.sources->len != 0) {
                        print_input_legacy_to_sources(*legacy_input_format,
                                legacy_input_paths, ctf_legacy_opts);
                        goto error;
@@ -2050,7 +1925,7 @@ bool validate_cfg(struct bt_config *cfg,
                }
 
                /* Make sure no non-legacy sinks are specified */
-               if (cfg->sinks->len != 0) {
+               if (cfg->cmd_data.convert.sinks->len != 0) {
                        print_output_legacy_to_sinks(*legacy_output_format,
                                text_legacy_opts);
                        goto error;
@@ -2111,15 +1986,16 @@ enum {
        OPT_END,
        OPT_FIELDS,
        OPT_HELP,
-       OPT_HELP_LEGACY,
        OPT_INPUT_FORMAT,
        OPT_LIST,
        OPT_NAMES,
        OPT_NO_DELTA,
+       OPT_OMIT_HOME_PLUGIN_PATH,
+       OPT_OMIT_SYSTEM_PLUGIN_PATH,
        OPT_OUTPUT_FORMAT,
        OPT_OUTPUT_PATH,
-       OPT_PATH,
        OPT_PARAMS,
+       OPT_PATH,
        OPT_PLUGIN_PATH,
        OPT_RESET_BASE_PARAMS,
        OPT_SINK,
@@ -2127,50 +2003,6 @@ enum {
        OPT_STREAM_INTERSECTION,
        OPT_TIMERANGE,
        OPT_VERBOSE,
-       OPT_VERSION,
-       OPT_OMIT_SYSTEM_PLUGIN_PATH,
-       OPT_OMIT_HOME_PLUGIN_PATH,
-};
-
-/* popt long option descriptions */
-static struct poptOption long_options[] = {
-       /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
-       { "base-params", 'b', POPT_ARG_STRING, NULL, OPT_BASE_PARAMS, NULL, NULL },
-       { "begin", '\0', POPT_ARG_STRING, NULL, OPT_BEGIN, NULL, NULL },
-       { "clock-cycles", '\0', POPT_ARG_NONE, NULL, OPT_CLOCK_CYCLES, NULL, NULL },
-       { "clock-date", '\0', POPT_ARG_NONE, NULL, OPT_CLOCK_DATE, NULL, NULL },
-       { "clock-force-correlate", '\0', POPT_ARG_NONE, NULL, OPT_CLOCK_FORCE_CORRELATE, NULL, NULL },
-       { "clock-gmt", '\0', POPT_ARG_NONE, NULL, OPT_CLOCK_GMT, NULL, NULL },
-       { "clock-offset", '\0', POPT_ARG_STRING, NULL, OPT_CLOCK_OFFSET, NULL, NULL },
-       { "clock-offset-ns", '\0', POPT_ARG_STRING, NULL, OPT_CLOCK_OFFSET_NS, NULL, NULL },
-       { "clock-seconds", '\0', POPT_ARG_NONE, NULL, OPT_CLOCK_SECONDS, NULL, NULL },
-       { "debug", 'd', POPT_ARG_NONE, NULL, OPT_DEBUG, NULL, NULL },
-       { "debug-info-dir", 0, POPT_ARG_STRING, NULL, OPT_DEBUG_INFO_DIR, NULL, NULL },
-       { "debug-info-full-path", 0, POPT_ARG_NONE, NULL, OPT_DEBUG_INFO_FULL_PATH, NULL, NULL },
-       { "debug-info-target-prefix", 0, POPT_ARG_STRING, NULL, OPT_DEBUG_INFO_TARGET_PREFIX, NULL, NULL },
-       { "end", '\0', POPT_ARG_STRING, NULL, OPT_END, NULL, NULL },
-       { "fields", 'f', POPT_ARG_STRING, NULL, OPT_FIELDS, NULL, NULL },
-       { "help", 'h', POPT_ARG_NONE, NULL, OPT_HELP, NULL, NULL },
-       { "help-legacy", '\0', POPT_ARG_NONE, NULL, OPT_HELP_LEGACY, NULL, NULL },
-       { "input-format", 'i', POPT_ARG_STRING, NULL, OPT_INPUT_FORMAT, NULL, NULL },
-       { "list", 'l', POPT_ARG_NONE, NULL, OPT_LIST, NULL, NULL },
-       { "names", 'n', POPT_ARG_STRING, NULL, OPT_NAMES, NULL, NULL },
-       { "no-delta", '\0', POPT_ARG_NONE, NULL, OPT_NO_DELTA, NULL, NULL },
-       { "output", 'w', POPT_ARG_STRING, NULL, OPT_OUTPUT_PATH, NULL, NULL },
-       { "output-format", 'o', POPT_ARG_STRING, NULL, OPT_OUTPUT_FORMAT, NULL, NULL },
-       { "path", 'P', POPT_ARG_STRING, NULL, OPT_PATH, NULL, NULL },
-       { "params", 'p', POPT_ARG_STRING, NULL, OPT_PARAMS, NULL, NULL },
-       { "plugin-path", '\0', POPT_ARG_STRING, NULL, OPT_PLUGIN_PATH, NULL, NULL },
-       { "reset-base-params", 'r', POPT_ARG_NONE, NULL, OPT_RESET_BASE_PARAMS, NULL, NULL },
-       { "sink", '\0', POPT_ARG_STRING, NULL, OPT_SINK, NULL, NULL },
-       { "source", '\0', POPT_ARG_STRING, NULL, OPT_SOURCE, NULL, NULL },
-       { "stream-intersection", '\0', POPT_ARG_NONE, NULL, OPT_STREAM_INTERSECTION, NULL, NULL },
-       { "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 },
 };
 
 /*
@@ -2196,9 +2028,9 @@ static void add_cfg_comp(struct bt_config *cfg,
                enum bt_config_component_dest dest)
 {
        if (dest == BT_CONFIG_COMPONENT_DEST_SOURCE) {
-               g_ptr_array_add(cfg->sources, cfg_comp);
+               g_ptr_array_add(cfg->cmd_data.convert.sources, cfg_comp);
        } else {
-               g_ptr_array_add(cfg->sinks, cfg_comp);
+               g_ptr_array_add(cfg->cmd_data.convert.sinks, cfg_comp);
        }
 }
 
@@ -2235,7 +2067,7 @@ not_found:
        return -1;
 }
 
-static int add_env_var_plugin_paths(struct bt_config *cfg)
+static int append_env_var_plugin_paths(struct bt_value *plugin_paths)
 {
        int ret = 0;
        const char *envvar;
@@ -2250,17 +2082,18 @@ static int add_env_var_plugin_paths(struct bt_config *cfg)
                goto end;
        }
 
-       ret = bt_config_append_plugin_paths(cfg->plugin_paths, envvar);
+       ret = bt_config_append_plugin_paths(plugin_paths, envvar);
 
 end:
        return ret;
 }
 
-static int append_home_and_system_plugin_paths(struct bt_config *cfg)
+static int append_home_and_system_plugin_paths(struct bt_value *plugin_paths,
+               bool omit_system_plugin_path, bool omit_home_plugin_path)
 {
        int ret;
 
-       if (!cfg->omit_home_plugin_path) {
+       if (!omit_home_plugin_path) {
                if (bt_common_is_setuid_setgid()) {
                        printf_debug("Skipping non-system plugin paths for setuid/setgid binary\n");
                } else {
@@ -2268,7 +2101,8 @@ static int append_home_and_system_plugin_paths(struct bt_config *cfg)
                                bt_common_get_home_plugin_path();
 
                        if (home_plugin_dir) {
-                               ret = bt_config_append_plugin_paths(cfg->plugin_paths,
+                               ret = bt_config_append_plugin_paths(
+                                       plugin_paths,
                                        home_plugin_dir);
                                free(home_plugin_dir);
 
@@ -2280,8 +2114,8 @@ static int append_home_and_system_plugin_paths(struct bt_config *cfg)
                }
        }
 
-       if (!cfg->omit_system_plugin_path) {
-               if (bt_config_append_plugin_paths(cfg->plugin_paths,
+       if (!omit_system_plugin_path) {
+               if (bt_config_append_plugin_paths(plugin_paths,
                                bt_common_get_system_plugin_path())) {
                        printf_err("Invalid system plugin path\n");
                        goto error;
@@ -2316,7 +2150,7 @@ error:
        return -1;
 }
 
-struct bt_config *bt_config_create(void)
+static struct bt_config *bt_config_base_create(enum bt_config_command command)
 {
        struct bt_config *cfg;
 
@@ -2328,113 +2162,167 @@ struct bt_config *bt_config_create(void)
        }
 
        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->command = command;
+       goto end;
 
-       cfg->sinks = g_ptr_array_new_with_free_func((GDestroyNotify) bt_put);
-       if (!cfg->sinks) {
-               print_err_oom();
-               goto error;
-       }
+error:
+       BT_PUT(cfg);
 
-       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;
 }
 
-/*
- * Initializes a created Babeltrace config object according to the
- * command-line arguments found in argv.
- *
- * Return value is set to the appropriate exit code to use.
- */
-int bt_config_init_from_args(struct bt_config *cfg, int argc, const char *argv[])
+static struct bt_config *bt_config_convert_create(
+               struct bt_value *initial_plugin_paths)
 {
-       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;
-       struct bt_value *legacy_input_paths = NULL;
-       struct bt_config_component *implicit_source_comp = NULL;
-       struct bt_config_component *cur_cfg_comp = NULL;
-       bool cur_is_implicit_source = false;
-       bool use_implicit_source = false;
-       enum bt_config_component_dest cur_cfg_comp_dest =
-               BT_CONFIG_COMPONENT_DEST_SOURCE;
-       struct bt_value *cur_base_params = NULL;
-       int opt, ret = 0;
-
-       memset(&ctf_legacy_opts, 0, sizeof(ctf_legacy_opts));
-       memset(&text_legacy_opts, 0, sizeof(text_legacy_opts));
+       struct bt_config *cfg;
 
-       text_legacy_opts.output = g_string_new(NULL);
-       if (!text_legacy_opts.output) {
+       /* Create config */
+       cfg = bt_config_base_create(BT_CONFIG_COMMAND_CONVERT);
+       if (!cfg) {
                print_err_oom();
                goto error;
        }
 
-       text_legacy_opts.dbg_info_dir = g_string_new(NULL);
-       if (!text_legacy_opts.dbg_info_dir) {
+       cfg->cmd_data.convert.sources = g_ptr_array_new_with_free_func(
+               (GDestroyNotify) bt_put);
+       if (!cfg->cmd_data.convert.sources) {
                print_err_oom();
                goto error;
        }
 
-       text_legacy_opts.dbg_info_target_prefix = g_string_new(NULL);
-       if (!text_legacy_opts.dbg_info_target_prefix) {
+       cfg->cmd_data.convert.sinks = g_ptr_array_new_with_free_func(
+               (GDestroyNotify) bt_put);
+       if (!cfg->cmd_data.convert.sinks) {
                print_err_oom();
                goto error;
        }
 
-       cur_base_params = bt_value_map_create();
-       if (!cur_base_params) {
-               print_err_oom();
-               goto error;
+       if (initial_plugin_paths) {
+               cfg->cmd_data.convert.plugin_paths =
+                       bt_get(initial_plugin_paths);
+       } else {
+               cfg->cmd_data.convert.plugin_paths = bt_value_array_create();
+               if (!cfg->cmd_data.convert.plugin_paths) {
+                       print_err_oom();
+                       goto error;
+               }
        }
 
-       legacy_input_paths = bt_value_array_create();
-       if (!legacy_input_paths) {
-               print_err_oom();
-               goto error;
-       }
+       goto end;
 
-       ret = add_env_var_plugin_paths(cfg);
-       if (ret) {
-               printf_err("Cannot append plugin paths from BABELTRACE_PLUGIN_PATH\n");
+error:
+       BT_PUT(cfg);
+
+end:
+       return cfg;
+}
+
+static struct bt_config *bt_config_list_plugins_create(
+               struct bt_value *initial_plugin_paths)
+{
+       struct bt_config *cfg;
+
+       /* Create config */
+       cfg = bt_config_base_create(BT_CONFIG_COMMAND_LIST_PLUGINS);
+       if (!cfg) {
+               print_err_oom();
                goto error;
        }
 
-       /* Note: implicit source never gets positional base params. */
-       implicit_source_comp = bt_config_component_from_arg(DEFAULT_SOURCE_COMPONENT_NAME);
-       if (implicit_source_comp) {
-               cur_cfg_comp = implicit_source_comp;
-               cur_is_implicit_source = true;
-               use_implicit_source = true;
+       if (initial_plugin_paths) {
+               cfg->cmd_data.list_plugins.plugin_paths =
+                       bt_get(initial_plugin_paths);
        } else {
-               printf_debug("Cannot find implicit source plugin \"%s\"",
-                       DEFAULT_SOURCE_COMPONENT_NAME);
-       }
-
-       /* Parse options */
-       pc = poptGetContext(NULL, argc, (const char **) argv, long_options, 0);
-       if (!pc) {
-               printf_err("Cannot get popt context\n");
-               goto error;
+               cfg->cmd_data.list_plugins.plugin_paths =
+                       bt_value_array_create();
+               if (!cfg->cmd_data.list_plugins.plugin_paths) {
+                       print_err_oom();
+                       goto error;
+               }
        }
 
-       poptReadDefaultConfig(pc, 0);
+       goto end;
+
+error:
+       BT_PUT(cfg);
+
+end:
+       return cfg;
+}
+
+/*
+ * Prints the list-plugins command usage.
+ */
+static
+void print_list_plugins_usage(FILE *fp)
+{
+       fprintf(fp, "Usage: babeltrace [GENERAL OPTIONS] list-plugins [OPTIONS]\n");
+       fprintf(fp, "\n");
+       fprintf(fp, "Options:\n");
+       fprintf(fp, "\n");
+       fprintf(fp, "      --omit-home-plugin-path       Omit home plugins from plugin search path\n");
+       fprintf(fp, "                                    (~/.local/lib/babeltrace/plugins)\n");
+       fprintf(fp, "      --omit-system-plugin-path     Omit system plugins from plugin search path\n");
+       fprintf(fp, "      --plugin-path=PATH[:PATH]...  Add PATH to the list of paths from which\n");
+       fprintf(fp, "                                    dynamic plugins can be loaded\n");
+       fprintf(fp, "  -h  --help                        Show this help and quit\n");
+       fprintf(fp, "\n");
+       fprintf(fp, "See `babeltrace --help` for the list of general options.\n");
+}
+
+static struct poptOption list_plugins_long_options[] = {
+       /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
+       { "help", 'h', POPT_ARG_NONE, NULL, OPT_HELP, NULL, NULL },
+       { "omit-home-plugin-path", '\0', POPT_ARG_NONE, NULL, OPT_OMIT_HOME_PLUGIN_PATH, NULL, NULL },
+       { "omit-system-plugin-path", '\0', POPT_ARG_NONE, NULL, OPT_OMIT_SYSTEM_PLUGIN_PATH, NULL, NULL },
+       { "plugin-path", '\0', POPT_ARG_STRING, NULL, OPT_PLUGIN_PATH, NULL, NULL },
+       { NULL, 0, 0, NULL, 0, NULL, NULL },
+};
+
+/*
+ * Creates a Babeltrace config object from the arguments of a
+ * list-plugins command.
+ *
+ * *retcode is set to the appropriate exit code to use.
+ */
+struct bt_config *bt_config_list_plugins_from_args(int argc, const char *argv[],
+               int *retcode, bool omit_system_plugin_path,
+               bool omit_home_plugin_path,
+               struct bt_value *initial_plugin_paths)
+{
+       poptContext pc = NULL;
+       char *arg = NULL;
+       int opt;
+       int ret;
+       struct bt_config *cfg = NULL;
+       const char *leftover;
+
+       *retcode = 0;
+       cfg = bt_config_list_plugins_create(initial_plugin_paths);
+       if (!cfg) {
+               print_err_oom();
+               goto error;
+       }
+
+       cfg->cmd_data.list_plugins.omit_system_plugin_path = omit_system_plugin_path;
+       cfg->cmd_data.list_plugins.omit_home_plugin_path = omit_home_plugin_path;
+       ret = append_env_var_plugin_paths(
+               cfg->cmd_data.list_plugins.plugin_paths);
+       if (ret) {
+               printf_err("Cannot append plugin paths from BABELTRACE_PLUGIN_PATH\n");
+               goto error;
+       }
+
+       /* Parse options */
+       pc = poptGetContext(NULL, argc, (const char **) argv,
+               list_plugins_long_options, 0);
+       if (!pc) {
+               printf_err("Cannot get popt context\n");
+               goto error;
+       }
+
+       poptReadDefaultConfig(pc, 0);
 
        while ((opt = poptGetNextOpt(pc)) > 0) {
                arg = poptGetOptArg(pc);
@@ -2444,17 +2332,378 @@ int bt_config_init_from_args(struct bt_config *cfg, int argc, const char *argv[]
                        if (bt_common_is_setuid_setgid()) {
                                printf_debug("Skipping non-system plugin paths for setuid/setgid binary\n");
                        } else {
-                               if (bt_config_append_plugin_paths(cfg->plugin_paths, arg)) {
+                               if (bt_config_append_plugin_paths(
+                                               cfg->cmd_data.list_plugins.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;
+                       cfg->cmd_data.list_plugins.omit_system_plugin_path = true;
                        break;
                case OPT_OMIT_HOME_PLUGIN_PATH:
-                       cfg->omit_home_plugin_path = true;
+                       cfg->cmd_data.list_plugins.omit_home_plugin_path = true;
+                       break;
+               case OPT_HELP:
+                       print_list_plugins_usage(stdout);
+                       *retcode = -1;
+                       BT_PUT(cfg);
+                       goto end;
+               default:
+                       printf_err("Unknown command-line option specified (option code %d)\n",
+                               opt);
+                       goto error;
+               }
+
+               free(arg);
+               arg = NULL;
+       }
+
+       /* Check for option parsing error */
+       if (opt < -1) {
+               printf_err("While parsing command-line options, at option %s: %s\n",
+                       poptBadOption(pc, 0), poptStrerror(opt));
+               goto error;
+       }
+
+       leftover = poptGetArg(pc);
+       if (leftover) {
+               printf_err("Invalid argument: %s\n", leftover);
+               goto error;
+       }
+
+       if (append_home_and_system_plugin_paths(
+                       cfg->cmd_data.list_plugins.plugin_paths,
+                       cfg->cmd_data.list_plugins.omit_system_plugin_path,
+                       cfg->cmd_data.list_plugins.omit_home_plugin_path)) {
+               printf_err("Cannot append home and system plugin paths\n");
+               goto error;
+       }
+
+       goto end;
+
+error:
+       *retcode = 1;
+       BT_PUT(cfg);
+
+end:
+       if (pc) {
+               poptFreeContext(pc);
+       }
+
+       free(arg);
+       return cfg;
+}
+
+
+/*
+ * Prints the legacy, Babeltrace 1.x command usage. Those options are
+ * still compatible in Babeltrace 2.x, but it is recommended to use
+ * the more generic plugin/component parameters instead of those
+ * hard-coded option names.
+ */
+static
+void print_legacy_usage(FILE *fp)
+{
+       fprintf(fp, "Usage: babeltrace [OPTIONS] INPUT...\n");
+       fprintf(fp, "\n");
+       fprintf(fp, "The following options are compatible with the Babeltrace 1.x options:\n");
+       fprintf(fp, "\n");
+       fprintf(fp, "      --clock-force-correlate  Assume that clocks are inherently correlated\n");
+       fprintf(fp, "                               across traces\n");
+       fprintf(fp, "  -d, --debug                  Enable debug mode\n");
+       fprintf(fp, "  -i, --input-format=FORMAT    Input trace format (default: ctf)\n");
+       fprintf(fp, "  -l, --list                   List available formats\n");
+       fprintf(fp, "  -o, --output-format=FORMAT   Output trace format (default: text)\n");
+       fprintf(fp, "  -v, --verbose                Enable verbose output\n");
+       fprintf(fp, "      --help-legacy            Show this help and quit\n");
+       fprintf(fp, "  -V, --version                Show version and quit\n");
+       fprintf(fp, "\n");
+       fprintf(fp, "  Available input formats:  ctf, lttng-live, ctf-metadata\n");
+       fprintf(fp, "  Available output formats: text, dummy\n");
+       fprintf(fp, "\n");
+       fprintf(fp, "Input formats specific options:\n");
+       fprintf(fp, "\n");
+       fprintf(fp, "  INPUT...                     Input trace file(s), directory(ies), or URLs\n");
+       fprintf(fp, "      --clock-offset=SEC       Set clock offset to SEC seconds\n");
+       fprintf(fp, "      --clock-offset-ns=NS     Set clock offset to NS nanoseconds\n");
+       fprintf(fp, "      --stream-intersection    Only process events when all streams are active\n");
+       fprintf(fp, "\n");
+       fprintf(fp, "text output format specific options:\n");
+       fprintf(fp, "  \n");
+       fprintf(fp, "      --clock-cycles           Print timestamps in clock cycles\n");
+       fprintf(fp, "      --clock-date             Print timestamp dates\n");
+       fprintf(fp, "      --clock-gmt              Print and parse timestamps in GMT time zone\n");
+       fprintf(fp, "                               (default: local time zone)\n");
+       fprintf(fp, "      --clock-seconds          Print the timestamps as [SEC.NS]\n");
+       fprintf(fp, "                               (default format: [HH:MM:SS.NS])\n");
+       fprintf(fp, "      --debug-info-dir=DIR     Search for debug info in directory DIR\n");
+       fprintf(fp, "                               (default: `/usr/lib/debug`)\n");
+       fprintf(fp, "      --debug-info-full-path   Show full debug info source and binary paths\n");
+       fprintf(fp, "      --debug-info-target-prefix=DIR  Use directory DIR as a prefix when looking\n");
+       fprintf(fp, "                                      up executables during debug info analysis\n");
+       fprintf(fp, "                               (default: `/usr/lib/debug`)\n");
+       fprintf(fp, "  -f, --fields=NAME[,NAME]...  Print additional fields:\n");
+       fprintf(fp, "                                 all, trace, trace:hostname, trace:domain,\n");
+       fprintf(fp, "                                 trace:procname, trace:vpid, loglevel, emf\n");
+       fprintf(fp, "                                 (default: trace:hostname, trace:procname,\n");
+       fprintf(fp, "                                           trace:vpid)\n");
+       fprintf(fp, "  -n, --names=NAME[,NAME]...   Print field names:\n");
+       fprintf(fp, "                                 payload (or arg or args)\n");
+       fprintf(fp, "                                 none, all, scope, header, context (or ctx)\n");
+       fprintf(fp, "                                 (default: payload, context)\n");
+       fprintf(fp, "      --no-delta               Do not print time delta between consecutive\n");
+       fprintf(fp, "                               events\n");
+       fprintf(fp, "  -w, --output=PATH            Write output to PATH (default: standard output)\n");
+}
+
+/*
+ * Prints the convert command usage.
+ */
+static
+void print_convert_usage(FILE *fp)
+{
+       fprintf(fp, "Usage: babeltrace [GENERAL OPTIONS] convert [OPTIONS]\n");
+       fprintf(fp, "\n");
+       fprintf(fp, "Options:\n");
+       fprintf(fp, "\n");
+       fprintf(fp, "  -b, --base-params=PARAMS          Set PARAMS as the current base parameters\n");
+       fprintf(fp, "                                    for the following component instances\n");
+       fprintf(fp, "                                    (see the expected format of PARAMS below)\n");
+       fprintf(fp, "      --begin=BEGIN                 Set the `begin` parameter of the latest\n");
+       fprintf(fp, "                                    source component instance to BEGIN\n");
+       fprintf(fp, "                                    (see the suggested format of BEGIN below)\n");
+       fprintf(fp, "  -d, --debug                       Enable debug mode\n");
+       fprintf(fp, "      --end=END                     Set the `end` parameter of the latest\n");
+       fprintf(fp, "                                    source component instance to END\n");
+       fprintf(fp, "                                    (see the suggested format of BEGIN below)\n");
+       fprintf(fp, "      --omit-home-plugin-path       Omit home plugins from plugin search path\n");
+       fprintf(fp, "                                    (~/.local/lib/babeltrace/plugins)\n");
+       fprintf(fp, "      --omit-system-plugin-path     Omit system plugins from plugin search path\n");
+       fprintf(fp, "  -p, --params=PARAMS               Set the parameters of the latest component\n");
+       fprintf(fp, "                                    instance (in command-line order) to PARAMS\n");
+       fprintf(fp, "                                    (see the expected format of PARAMS below)\n");
+       fprintf(fp, "  -P, --path=PATH                   Set the `path` parameter of the latest\n");
+       fprintf(fp, "                                    component instance to PATH\n");
+       fprintf(fp, "      --plugin-path=PATH[:PATH]...  Add PATH to the list of paths from which\n");
+       fprintf(fp, "                                    dynamic plugins can be loaded\n");
+       fprintf(fp, "  -r, --reset-base-params           Reset the current base parameters of the\n");
+       fprintf(fp, "                                    following source and sink component\n");
+       fprintf(fp, "                                    instances to an empty map\n");
+       fprintf(fp, "  -o, --sink=PLUGIN.COMPCLS         Instantiate a sink component from plugin\n");
+       fprintf(fp, "                                    PLUGIN and component class COMPCLS (may be\n");
+       fprintf(fp, "                                    repeated)\n");
+       fprintf(fp, "  -i, --source=PLUGIN.COMPCLS       Instantiate a source component from plugin\n");
+       fprintf(fp, "                                    PLUGIN and component class COMPCLS (may be\n");
+       fprintf(fp, "                                    repeated)\n");
+       fprintf(fp, "      --timerange=TIMERANGE         Set time range to TIMERANGE: BEGIN,END or\n");
+       fprintf(fp, "                                    [BEGIN,END] (literally `[` and `]`)\n");
+       fprintf(fp, "                                    (suggested format of BEGIN/END below)\n");
+       fprintf(fp, "  -v, --verbose                     Enable verbose output\n");
+       fprintf(fp, "  -h  --help                        Show this help and quit\n");
+       fprintf(fp, "\n");
+       fprintf(fp, "See `babeltrace --help` for the list of general options.\n");
+       fprintf(fp, "\n\n");
+       fprintf(fp, "Suggested format of BEGIN and END\n");
+       fprintf(fp, "---------------------------------\n");
+       fprintf(fp, "\n");
+       fprintf(fp, "    [YYYY-MM-DD [hh:mm:]]ss[.nnnnnnnnn]\n");
+       fprintf(fp, "\n\n");
+       fprintf(fp, "Expected format of PARAMS\n");
+       fprintf(fp, "-------------------------\n");
+       fprintf(fp, "\n");
+       fprintf(fp, "    PARAM=VALUE[,PARAM=VALUE]...\n");
+       fprintf(fp, "\n");
+       fprintf(fp, "The parameter string is a comma-separated list of PARAM=VALUE assignments,\n");
+       fprintf(fp, "where PARAM is the parameter name (C identifier plus [:.-] characters), and\n");
+       fprintf(fp, "VALUE can be one of:\n");
+       fprintf(fp, "\n");
+       fprintf(fp, "* `null`, `nul`, `NULL`: null value (no backticks).\n");
+       fprintf(fp, "* `true`, `TRUE`, `yes`, `YES`: true boolean value (no backticks).\n");
+       fprintf(fp, "* `false`, `FALSE`, `no`, `NO`: false boolean value (no backticks).\n");
+       fprintf(fp, "* Binary (`0b` prefix), octal (`0` prefix), decimal, or hexadecimal\n");
+       fprintf(fp, "  (`0x` prefix) signed 64-bit integer.\n");
+       fprintf(fp, "* Double precision floating point number (scientific notation is accepted).\n");
+       fprintf(fp, "* Unquoted string with no special characters, and not matching any of\n");
+       fprintf(fp, "  the null and boolean value symbols above.\n");
+       fprintf(fp, "* Double-quoted string (accepts escape characters).\n");
+       fprintf(fp, "\n");
+       fprintf(fp, "Whitespaces are allowed around individual `=` and `,` tokens.\n");
+       fprintf(fp, "\n");
+       fprintf(fp, "Example:\n");
+       fprintf(fp, "\n");
+       fprintf(fp, "    many=null, fresh=yes, condition=false, squirrel=-782329,\n");
+       fprintf(fp, "    observe=3.14, simple=beef, needs-quotes=\"some string\",\n");
+       fprintf(fp, "    escape.chars-are:allowed=\"this is a \\\" double quote\"\n");
+       fprintf(fp, "\n");
+       fprintf(fp, "IMPORTANT: Make sure to single-quote the whole argument when you run babeltrace\n");
+       fprintf(fp, "from a shell.\n");
+}
+
+static struct poptOption convert_long_options[] = {
+       /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
+       { "base-params", 'b', POPT_ARG_STRING, NULL, OPT_BASE_PARAMS, NULL, NULL },
+       { "begin", '\0', POPT_ARG_STRING, NULL, OPT_BEGIN, NULL, NULL },
+       { "clock-cycles", '\0', POPT_ARG_NONE, NULL, OPT_CLOCK_CYCLES, NULL, NULL },
+       { "clock-date", '\0', POPT_ARG_NONE, NULL, OPT_CLOCK_DATE, NULL, NULL },
+       { "clock-force-correlate", '\0', POPT_ARG_NONE, NULL, OPT_CLOCK_FORCE_CORRELATE, NULL, NULL },
+       { "clock-gmt", '\0', POPT_ARG_NONE, NULL, OPT_CLOCK_GMT, NULL, NULL },
+       { "clock-offset", '\0', POPT_ARG_STRING, NULL, OPT_CLOCK_OFFSET, NULL, NULL },
+       { "clock-offset-ns", '\0', POPT_ARG_STRING, NULL, OPT_CLOCK_OFFSET_NS, NULL, NULL },
+       { "clock-seconds", '\0', POPT_ARG_NONE, NULL, OPT_CLOCK_SECONDS, NULL, NULL },
+       { "debug", 'd', POPT_ARG_NONE, NULL, OPT_DEBUG, NULL, NULL },
+       { "debug-info-dir", 0, POPT_ARG_STRING, NULL, OPT_DEBUG_INFO_DIR, NULL, NULL },
+       { "debug-info-full-path", 0, POPT_ARG_NONE, NULL, OPT_DEBUG_INFO_FULL_PATH, NULL, NULL },
+       { "debug-info-target-prefix", 0, POPT_ARG_STRING, NULL, OPT_DEBUG_INFO_TARGET_PREFIX, NULL, NULL },
+       { "end", '\0', POPT_ARG_STRING, NULL, OPT_END, NULL, NULL },
+       { "fields", 'f', POPT_ARG_STRING, NULL, OPT_FIELDS, NULL, NULL },
+       { "help", 'h', POPT_ARG_NONE, NULL, OPT_HELP, NULL, NULL },
+       { "input-format", 'i', POPT_ARG_STRING, NULL, OPT_INPUT_FORMAT, NULL, NULL },
+       { "names", 'n', POPT_ARG_STRING, NULL, OPT_NAMES, NULL, NULL },
+       { "no-delta", '\0', POPT_ARG_NONE, NULL, OPT_NO_DELTA, NULL, NULL },
+       { "omit-home-plugin-path", '\0', POPT_ARG_NONE, NULL, OPT_OMIT_HOME_PLUGIN_PATH, NULL, NULL },
+       { "omit-system-plugin-path", '\0', POPT_ARG_NONE, NULL, OPT_OMIT_SYSTEM_PLUGIN_PATH, NULL, NULL },
+       { "output", 'w', POPT_ARG_STRING, NULL, OPT_OUTPUT_PATH, NULL, NULL },
+       { "output-format", 'o', POPT_ARG_STRING, NULL, OPT_OUTPUT_FORMAT, NULL, NULL },
+       { "params", 'p', POPT_ARG_STRING, NULL, OPT_PARAMS, NULL, NULL },
+       { "path", 'P', POPT_ARG_STRING, NULL, OPT_PATH, NULL, NULL },
+       { "plugin-path", '\0', POPT_ARG_STRING, NULL, OPT_PLUGIN_PATH, NULL, NULL },
+       { "reset-base-params", 'r', POPT_ARG_NONE, NULL, OPT_RESET_BASE_PARAMS, NULL, NULL },
+       { "sink", '\0', POPT_ARG_STRING, NULL, OPT_SINK, NULL, NULL },
+       { "source", '\0', POPT_ARG_STRING, NULL, OPT_SOURCE, NULL, NULL },
+       { "stream-intersection", '\0', POPT_ARG_NONE, NULL, OPT_STREAM_INTERSECTION, NULL, NULL },
+       { "timerange", '\0', POPT_ARG_STRING, NULL, OPT_TIMERANGE, NULL, NULL },
+       { "verbose", 'v', POPT_ARG_NONE, NULL, OPT_VERBOSE, NULL, NULL },
+       { NULL, 0, 0, NULL, 0, NULL, NULL },
+};
+
+/*
+ * Creates a Babeltrace config object from the arguments of a convert
+ * command.
+ *
+ * *retcode is set to the appropriate exit code to use.
+ */
+struct bt_config *bt_config_convert_from_args(int argc, const char *argv[],
+               int *retcode, bool omit_system_plugin_path,
+               bool omit_home_plugin_path,
+               struct bt_value *initial_plugin_paths)
+{
+       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;
+       struct bt_value *legacy_input_paths = NULL;
+       struct bt_config_component *implicit_source_comp = NULL;
+       struct bt_config_component *cur_cfg_comp = NULL;
+       bool cur_is_implicit_source = false;
+       bool use_implicit_source = false;
+       enum bt_config_component_dest cur_cfg_comp_dest =
+               BT_CONFIG_COMPONENT_DEST_SOURCE;
+       struct bt_value *cur_base_params = NULL;
+       int opt, ret = 0;
+       struct bt_config *cfg = NULL;
+
+       *retcode = 0;
+       memset(&ctf_legacy_opts, 0, sizeof(ctf_legacy_opts));
+       memset(&text_legacy_opts, 0, sizeof(text_legacy_opts));
+
+       if (argc <= 1) {
+               print_convert_usage(stdout);
+               *retcode = -1;
+               goto end;
+       }
+
+       cfg = bt_config_convert_create(initial_plugin_paths);
+       if (!cfg) {
+               print_err_oom();
+               goto error;
+       }
+
+       cfg->cmd_data.convert.omit_system_plugin_path = omit_system_plugin_path;
+       cfg->cmd_data.convert.omit_home_plugin_path = omit_home_plugin_path;
+       text_legacy_opts.output = g_string_new(NULL);
+       if (!text_legacy_opts.output) {
+               print_err_oom();
+               goto error;
+       }
+
+       text_legacy_opts.dbg_info_dir = g_string_new(NULL);
+       if (!text_legacy_opts.dbg_info_dir) {
+               print_err_oom();
+               goto error;
+       }
+
+       text_legacy_opts.dbg_info_target_prefix = g_string_new(NULL);
+       if (!text_legacy_opts.dbg_info_target_prefix) {
+               print_err_oom();
+               goto error;
+       }
+
+       cur_base_params = bt_value_map_create();
+       if (!cur_base_params) {
+               print_err_oom();
+               goto error;
+       }
+
+       legacy_input_paths = bt_value_array_create();
+       if (!legacy_input_paths) {
+               print_err_oom();
+               goto error;
+       }
+
+       ret = append_env_var_plugin_paths(cfg->cmd_data.convert.plugin_paths);
+       if (ret) {
+               printf_err("Cannot append plugin paths from BABELTRACE_PLUGIN_PATH\n");
+               goto error;
+       }
+
+       /* Note: implicit source never gets positional base params. */
+       implicit_source_comp = bt_config_component_from_arg(DEFAULT_SOURCE_COMPONENT_NAME);
+       if (implicit_source_comp) {
+               cur_cfg_comp = implicit_source_comp;
+               cur_is_implicit_source = true;
+               use_implicit_source = true;
+       } else {
+               printf_debug("Cannot find implicit source plugin \"%s\"",
+                       DEFAULT_SOURCE_COMPONENT_NAME);
+       }
+
+       /* Parse options */
+       pc = poptGetContext(NULL, argc, (const char **) argv,
+               convert_long_options, 0);
+       if (!pc) {
+               printf_err("Cannot get popt context\n");
+               goto error;
+       }
+
+       poptReadDefaultConfig(pc, 0);
+
+       while ((opt = poptGetNextOpt(pc)) > 0) {
+               arg = poptGetOptArg(pc);
+
+               switch (opt) {
+               case OPT_PLUGIN_PATH:
+                       if (bt_common_is_setuid_setgid()) {
+                               printf_debug("Skipping non-system plugin paths for setuid/setgid binary\n");
+                       } else {
+                               if (bt_config_append_plugin_paths(
+                                               cfg->cmd_data.convert.plugin_paths,
+                                               arg)) {
+                                       printf_err("Invalid --plugin-path option's argument\n");
+                                       goto error;
+                               }
+                       }
+                       break;
+               case OPT_OMIT_SYSTEM_PLUGIN_PATH:
+                       cfg->cmd_data.convert.omit_system_plugin_path = true;
+                       break;
+               case OPT_OMIT_HOME_PLUGIN_PATH:
+                       cfg->cmd_data.convert.omit_home_plugin_path = true;
                        break;
                case OPT_OUTPUT_PATH:
                        if (text_legacy_opts.output->len > 0) {
@@ -2528,7 +2777,7 @@ int bt_config_init_from_args(struct bt_config *cfg, int argc, const char *argv[]
                        cur_cfg_comp->params = bt_value_copy(cur_base_params);
                        if (!cur_cfg_comp->params) {
                                print_err_oom();
-                               goto end;
+                               goto error;
                        }
 
                        cur_cfg_comp_dest = BT_CONFIG_COMPONENT_DEST_SOURCE;
@@ -2590,7 +2839,7 @@ int bt_config_init_from_args(struct bt_config *cfg, int argc, const char *argv[]
                        cur_cfg_comp->params = bt_value_copy(cur_base_params);
                        if (!cur_cfg_comp->params) {
                                print_err_oom();
-                               goto end;
+                               goto error;
                        }
 
                        cur_cfg_comp_dest = BT_CONFIG_COMPONENT_DEST_SINK;
@@ -2742,7 +2991,7 @@ int bt_config_init_from_args(struct bt_config *cfg, int argc, const char *argv[]
                        ctf_legacy_opts.stream_intersection = true;
                        break;
                case OPT_CLOCK_FORCE_CORRELATE:
-                       cfg->force_correlate = true;
+                       cfg->cmd_data.convert.force_correlate = true;
                        break;
                case OPT_BEGIN:
                        if (!cur_cfg_comp) {
@@ -2806,16 +3055,9 @@ int bt_config_init_from_args(struct bt_config *cfg, int argc, const char *argv[]
                        break;
                }
                case OPT_HELP:
-                       print_usage(stdout);
-                       goto end;
-               case OPT_HELP_LEGACY:
-                       print_legacy_usage(stdout);
-                       goto end;
-               case OPT_VERSION:
-                       print_version();
-                       goto end;
-               case OPT_LIST:
-                       cfg->do_list = true;
+                       print_convert_usage(stdout);
+                       *retcode = -1;
+                       BT_PUT(cfg);
                        goto end;
                case OPT_VERBOSE:
                        cfg->verbose = true;
@@ -2833,11 +3075,6 @@ int bt_config_init_from_args(struct bt_config *cfg, int argc, const char *argv[]
                arg = NULL;
        }
 
-       if (argc <= 1) {
-               print_usage(stdout);
-               goto end;
-       }
-
        /* Check for option parsing error */
        if (opt < -1) {
                printf_err("While parsing command-line options, at option %s: %s\n",
@@ -2860,7 +3097,11 @@ int bt_config_init_from_args(struct bt_config *cfg, int argc, const char *argv[]
                }
        }
 
-       if (append_home_and_system_plugin_paths(cfg)) {
+       if (append_home_and_system_plugin_paths(
+                       cfg->cmd_data.convert.plugin_paths,
+                       cfg->cmd_data.convert.omit_system_plugin_path,
+                       cfg->cmd_data.convert.omit_home_plugin_path)) {
+               printf_err("Cannot append home and system plugin paths\n");
                goto error;
        }
 
@@ -2883,13 +3124,15 @@ int bt_config_init_from_args(struct bt_config *cfg, int argc, const char *argv[]
         * component configurations.
         */
        if (legacy_input_format) {
-               if (append_sources_from_legacy_opts(cfg->sources,
+               if (append_sources_from_legacy_opts(
+                               cfg->cmd_data.convert.sources,
                                legacy_input_format, &ctf_legacy_opts,
                                legacy_input_paths)) {
                        printf_err("Cannot convert legacy input format options to source component instance(s)\n");
                        goto error;
                }
-               if (append_sources_from_implicit_params(cfg->sources,
+               if (append_sources_from_implicit_params(
+                               cfg->cmd_data.convert.sources,
                                implicit_source_comp)) {
                        printf_err("Cannot initialize legacy component parameters\n");
                        goto error;
@@ -2914,14 +3157,14 @@ int bt_config_init_from_args(struct bt_config *cfg, int argc, const char *argv[]
         * component configurations.
         */
        if (legacy_output_format) {
-               if (append_sinks_from_legacy_opts(cfg->sinks,
+               if (append_sinks_from_legacy_opts(cfg->cmd_data.convert.sinks,
                                legacy_output_format, &text_legacy_opts)) {
                        printf_err("Cannot convert legacy output format options to sink component instance(s)\n");
                        goto error;
                }
        }
 
-       if (cfg->sinks->len == 0) {
+       if (cfg->cmd_data.convert.sinks->len == 0) {
                /* Use implicit sink as default. */
                cur_cfg_comp = bt_config_component_from_arg(DEFAULT_SINK_COMPONENT_NAME);
                if (!cur_cfg_comp) {
@@ -2936,7 +3179,9 @@ int bt_config_init_from_args(struct bt_config *cfg, int argc, const char *argv[]
        goto end;
 
 error:
-       ret = 1;
+       *retcode = 1;
+       BT_PUT(cfg);
+
 end:
        if (pc) {
                poptFreeContext(pc);
@@ -2961,5 +3206,145 @@ end:
        BT_PUT(text_legacy_opts.names);
        BT_PUT(text_legacy_opts.fields);
        BT_PUT(legacy_input_paths);
-       return ret;
+       return cfg;
+}
+
+/*
+ * Prints the Babeltrace 2.x general usage.
+ */
+static
+void print_gen_usage(FILE *fp)
+{
+       fprintf(fp, "Usage: babeltrace [GENERAL OPTIONS] [COMMAND] [COMMAND OPTIONS]\n");
+       fprintf(fp, "\n");
+       fprintf(fp, "General options:\n");
+       fprintf(fp, "\n");
+       fprintf(fp, "  -d, --debug        Enable debug mode\n");
+       fprintf(fp, "  -h  --help         Show this help and quit\n");
+       fprintf(fp, "      --help-legacy  Show Babeltrace 1.x legacy help and quit\n");
+       fprintf(fp, "  -v, --verbose      Enable verbose output\n");
+       fprintf(fp, "  -V, --version      Show version and quit\n");
+       fprintf(fp, "\n");
+       fprintf(fp, "Available commands:\n");
+       fprintf(fp, "\n");
+       fprintf(fp, "    convert       Build a trace conversion graph and run it (default)\n");
+       fprintf(fp, "    list-plugins  List available plugins and their content\n");
+       fprintf(fp, "\n");
+       fprintf(fp, "Use `babeltrace COMMAND --help` to show the help of COMMAND.\n");
+}
+
+struct bt_config *bt_config_from_args(int argc, const char *argv[],
+               int *retcode, bool omit_system_plugin_path,
+               bool omit_home_plugin_path,
+               struct bt_value *initial_plugin_paths)
+{
+       struct bt_config *config = NULL;
+       bool verbose = false;
+       bool debug = false;
+       int i;
+       enum bt_config_command command = -1;
+       const char **command_argv = NULL;
+       int command_argc = -1;
+       const char *command_name = NULL;
+
+       *retcode = -1;
+
+       if (argc <= 1) {
+               print_gen_usage(stdout);
+               goto end;
+       }
+
+       for (i = 1; i < argc; i++) {
+               const char *cur_arg = argv[i];
+
+               if (strcmp(cur_arg, "-d") == 0 ||
+                               strcmp(cur_arg, "--debug") == 0) {
+                       debug = true;
+               } else if (strcmp(cur_arg, "-v") == 0 ||
+                               strcmp(cur_arg, "--verbose") == 0) {
+                       verbose = true;
+               } else if (strcmp(cur_arg, "-V") == 0 ||
+                               strcmp(cur_arg, "--version") == 0) {
+                       print_version();
+                       goto end;
+               } else if (strcmp(cur_arg, "-h") == 0 ||
+                               strcmp(cur_arg, "--help") == 0) {
+                       print_gen_usage(stdout);
+                       goto end;
+               } else if (strcmp(cur_arg, "--help-legacy") == 0) {
+                       print_legacy_usage(stdout);
+                       goto end;
+               } else {
+                       /*
+                        * First unknown argument: is it a known command
+                        * name?
+                        */
+                       if (strcmp(cur_arg, "convert") == 0) {
+                               command = BT_CONFIG_COMMAND_CONVERT;
+                               command_argv = &argv[i];
+                               command_argc = argc - i;
+                               command_name = cur_arg;
+                       } else if (strcmp(cur_arg, "list-plugins") == 0) {
+                               command = BT_CONFIG_COMMAND_LIST_PLUGINS;
+                               command_argv = &argv[i];
+                               command_argc = argc - i;
+                               command_name = cur_arg;
+                       } else {
+                               /*
+                                * Unknown argument, but not a known
+                                * command name: assume the whole
+                                * arguments are for the default convert
+                                * command.
+                                */
+                               command = BT_CONFIG_COMMAND_CONVERT;
+                               command_argv = argv;
+                               command_argc = argc;
+                       }
+                       break;
+               }
+       }
+
+       if ((int) command < 0) {
+               /*
+                * We only got non-help, non-version general options
+                * like --verbose and --debug, without any other
+                * arguments, so we can't do anything useful: print the
+                * usage and quit.
+                */
+               print_gen_usage(stdout);
+               goto end;
+       }
+
+       assert(command_argv);
+       assert(command_argc >= 0);
+
+       switch (command) {
+       case BT_CONFIG_COMMAND_CONVERT:
+               config = bt_config_convert_from_args(command_argc, command_argv,
+                       retcode, omit_system_plugin_path,
+                       omit_home_plugin_path, initial_plugin_paths);
+               break;
+       case BT_CONFIG_COMMAND_LIST_PLUGINS:
+               config = bt_config_list_plugins_from_args(command_argc,
+                       command_argv, retcode, omit_system_plugin_path,
+                       omit_home_plugin_path, initial_plugin_paths);
+               break;
+       default:
+               assert(false);
+       }
+
+       if (config) {
+               if (verbose) {
+                       config->verbose = true;
+               }
+
+               if (debug) {
+                       config->debug = true;
+               }
+
+               config->command_name = command_name;
+       }
+
+end:
+       return config;
 }
This page took 0.037457 seconds and 4 git commands to generate.