Fix: print usage even if omit arguments are received
[babeltrace.git] / converter / babeltrace-cfg.c
index ee951bc80ae7da49f34a7f114f2737813e7eef68..6beaf383bfdfef77c2f69f0be9020986699a9891 100644 (file)
 #include <babeltrace/values.h>
 #include <popt.h>
 #include <glib.h>
+#include <sys/types.h>
+#include <pwd.h>
 #include "babeltrace-cfg.h"
 
+#define SYSTEM_PLUGIN_PATH             INSTALL_LIBDIR "/babeltrace/plugins"
+#define DEFAULT_SOURCE_COMPONENT_NAME  "ctf.fs"
+#define DEFAULT_SINK_COMPONENT_NAME    "text.text"
+#define HOME_ENV_VAR                   "HOME"
+#define HOME_SUBPATH                   "/.babeltrace/plugins"
+
 /*
  * Error printf() macro which prepends "Error: " the first time it's
  * called. This gives a nicer feel than having a bunch of error prefixes
@@ -140,6 +148,9 @@ enum legacy_output_format {
        LEGACY_OUTPUT_FORMAT_DUMMY,
 };
 
+static bool omit_system_plugin_path;
+static bool omit_home_plugin_path;
+
 /*
  * Prints the "out of memory" error.
  */
@@ -280,7 +291,7 @@ int ini_handle_state(struct ini_parsing_state *state)
 
                if (bt_value_map_has_key(state->params, state->last_map_key)) {
                        g_string_append_printf(state->ini_error,
-                               "Duplicate parameter key: \"%s\"\n",
+                               "Duplicate parameter key: `%s`\n",
                                state->last_map_key);
                        goto error;
                }
@@ -589,9 +600,7 @@ end:
 
 /*
  * Returns the parameters map value object from a command-line
- * source/sink option's argument. arg is the full argument, including
- * the plugin/component names, the optional colon, and the optional
- * parameters.
+ * parameter option's argument.
  *
  * Return value is owned by the caller.
  */
@@ -599,19 +608,8 @@ static
 struct bt_value *bt_value_from_arg(const char *arg)
 {
        struct bt_value *params = NULL;
-       const char *colon;
-       const char *params_string;
        GString *ini_error = NULL;
 
-       /* Isolate parameters */
-       colon = strchr(arg, ':');
-       if (!colon) {
-               /* No colon: empty parameters */
-               params = bt_value_map_create();
-               goto end;
-       }
-
-       params_string = colon + 1;
        ini_error = g_string_new(NULL);
        if (!ini_error) {
                print_err_oom();
@@ -619,7 +617,7 @@ struct bt_value *bt_value_from_arg(const char *arg)
        }
 
        /* Try INI-style parsing */
-       params = bt_value_from_ini(params_string, ini_error);
+       params = bt_value_from_ini(arg, ini_error);
        if (!params) {
                printf_err("%s", ini_error->str);
                goto end;
@@ -634,9 +632,12 @@ end:
 
 /*
  * Returns the plugin and component names from a command-line
- * source/sink option's argument. arg is the full argument, including
- * the plugin/component names, the optional colon, and the optional
- * parameters.
+ * source/sink option's argument. arg must have the following format:
+ *
+ *     PLUGIN.COMPONENT
+ *
+ * where PLUGIN is the plugin name, and COMPONENT is the component
+ * name.
  *
  * On success, both *plugin and *component are not NULL. *plugin
  * and *component are owned by the caller.
@@ -646,48 +647,41 @@ void plugin_component_names_from_arg(const char *arg, char **plugin,
                char **component)
 {
        const char *dot;
-       const char *colon;
+       const char *end;
        size_t plugin_len;
        size_t component_len;
 
+       /* Initialize both return values to NULL: not found */
        *plugin = NULL;
        *component = NULL;
 
        dot = strchr(arg, '.');
-       if (!dot || dot == arg) {
+       if (!dot) {
+               /* No dot */
                goto end;
        }
 
-       colon = strchr(dot, ':');
-       if (colon == dot) {
-               goto end;
-       }
-       if (!colon) {
-               colon = arg + strlen(arg);
-       }
-
+       end = arg + strlen(arg);
        plugin_len = dot - arg;
-       component_len = colon - dot - 1;
+       component_len = end - dot - 1;
        if (plugin_len == 0 || component_len == 0) {
                goto end;
        }
 
-       *plugin = malloc(plugin_len + 1);
+       *plugin = g_malloc0(plugin_len + 1);
        if (!*plugin) {
                print_err_oom();
                goto end;
        }
 
-       (*plugin)[plugin_len] = '\0';
-       memcpy(*plugin, arg, plugin_len);
-       *component = malloc(component_len + 1);
+       g_strlcpy(*plugin, arg, plugin_len + 1);
+       *component = g_malloc0(component_len + 1);
        if (!*component) {
                print_err_oom();
                goto end;
        }
 
-       (*component)[component_len] = '\0';
-       memcpy(*component, dot + 1, component_len);
+       g_strlcpy(*component, dot + 1, component_len + 1);
 
 end:
        return;
@@ -739,20 +733,19 @@ void print_legacy_usage(FILE *fp)
        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 timestamps in GMT time zone\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, "                               (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, "                               (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, "                                 callsite\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");
@@ -772,50 +765,68 @@ void print_usage(FILE *fp)
 {
        fprintf(fp, "Usage: babeltrace [OPTIONS]\n");
        fprintf(fp, "\n");
-       fprintf(fp, "  -h  --help                        Show this help\n");
-       fprintf(fp, "      --help-legacy                 Show Babeltrace 1.x legacy options\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, "  -d, --debug                       Enable debug mode\n");
        fprintf(fp, "  -l, --list                        List available plugins and their components\n");
-       fprintf(fp, "  -p, --plugin-path=PATH[:PATH]...  Set paths from which dynamic plugins can be\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, "  -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, "      --plugin-path=PATH[:PATH]...  Set paths from which dynamic plugins can be\n");
        fprintf(fp, "                                    loaded to PATH\n");
-       fprintf(fp, "  -i, --source=SOURCE               Add source plugin/component SOURCE and its\n");
-       fprintf(fp, "                                    parameters to the active sources (may be\n");
-       fprintf(fp, "                                    repeated; see the exact format below)\n");
-       fprintf(fp, "  -o, --sink=SINK                   Add sink plugin/component SINK and its\n");
-       fprintf(fp, "                                    parameters to the active sinks (may be\n");
-       fprintf(fp, "                                    repeated; see the exact format below)\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, "      --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");
        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, "SOURCE/SINK argument format:\n");
-       fprintf(fp, "\n");
-       fprintf(fp, "  One of:\n");
+       fprintf(fp, "    PARAM=VALUE[,PARAM=VALUE]...\n");
        fprintf(fp, "\n");
-       fprintf(fp, "    PLUGIN.COMPONENT\n");
-       fprintf(fp, "      Load component COMPONENT from plugin PLUGIN with its default parameters.\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, "    PLUGIN.COMPONENT:PARAM=VALUE[,PARAM=VALUE]...\n");
-       fprintf(fp, "      Load component COMPONENT from plugin PLUGIN with the specified parameters.\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, "      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, "Whitespaces are allowed around individual `=` and `,` tokens.\n");
        fprintf(fp, "\n");
-       fprintf(fp, "        * \"null\", \"nul\", \"NULL\": null value (no double quotes)\n");
-       fprintf(fp, "        * \"true\", \"TRUE\", \"yes\", \"YES\": true boolean value (no double quotes)\n");
-       fprintf(fp, "        * \"false\", \"FALSE\", \"no\", \"NO\": false boolean value (no double quotes)\n");
-       fprintf(fp, "        * Binary (\"0b\" prefix), octal (\"0\" prefix), decimal, or\n");
-       fprintf(fp, "          hexadecimal (\"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, "Example:\n");
        fprintf(fp, "\n");
-       fprintf(fp, "      Example:\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, "          plugin.comp: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, "IMPORTANT: Make sure to single-quote the whole argument when you run babeltrace\n");
+       fprintf(fp, "from a shell.\n");
 }
 
 /*
@@ -847,16 +858,15 @@ end:
 }
 
 /*
- * Creates a component configuration using the given plugin name,
- * component name, and parameters. plugin_name and component_name
- * are copied (belong to the return value), and a reference to
- * params is acquired.
+ * Creates a component configuration using the given plugin name and
+ * component name. plugin_name and component_name are copied (belong to
+ * the return value).
  *
  * Return value is owned by the caller.
  */
 static
 struct bt_config_component *bt_config_component_create(const char *plugin_name,
-               const char *component_name, struct bt_value *params)
+               const char *component_name)
 {
        struct bt_config_component *cfg_component = NULL;
 
@@ -879,7 +889,13 @@ struct bt_config_component *bt_config_component_create(const char *plugin_name,
                goto error;
        }
 
-       cfg_component->params = bt_get(params);
+       /* Start with empty parameters */
+       cfg_component->params = bt_value_map_create();
+       if (!cfg_component->params) {
+               print_err_oom();
+               goto error;
+       }
+
        goto end;
 
 error:
@@ -891,9 +907,7 @@ end:
 
 /*
  * Creates a component configuration from a command-line source/sink
- * option's argument. arg is the full argument, including
- * the plugin/component names, the optional colon, and the optional
- * parameters.
+ * option's argument.
  */
 static
 struct bt_config_component *bt_config_component_from_arg(const char *arg)
@@ -901,22 +915,15 @@ struct bt_config_component *bt_config_component_from_arg(const char *arg)
        struct bt_config_component *bt_config_component = NULL;
        char *plugin_name;
        char *component_name;
-       struct bt_value *params = NULL;
 
        plugin_component_names_from_arg(arg, &plugin_name, &component_name);
        if (!plugin_name || !component_name) {
-               printf_err("Cannot get plugin or component name\n");
-               goto error;
-       }
-
-       params = bt_value_from_arg(arg);
-       if (!params) {
-               printf_err("Cannot parse parameters\n");
+               printf_err("Cannot get plugin or component class name\n");
                goto error;
        }
 
        bt_config_component = bt_config_component_create(plugin_name,
-               component_name, params);
+               component_name);
        if (!bt_config_component) {
                goto error;
        }
@@ -927,9 +934,8 @@ error:
        BT_PUT(bt_config_component);
 
 end:
-       free(plugin_name);
-       free(component_name);
-       BT_PUT(params);
+       g_free(plugin_name);
+       g_free(component_name);
        return bt_config_component;
 }
 
@@ -961,6 +967,12 @@ end:
        return;
 }
 
+static
+bool is_setuid_setgid(void)
+{
+       return (geteuid() != getuid() || getegid() != getgid());
+}
+
 /*
  * Extracts the various paths from the string arg, delimited by ':',
  * and converts them to an array value object.
@@ -970,18 +982,12 @@ 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);
 
-       plugin_paths = bt_value_array_create();
-       if (!plugin_paths) {
-               print_err_oom();
-               goto error;
-       }
-
        while (at < end) {
                int ret;
                GString *path;
@@ -1016,13 +1022,9 @@ struct bt_value *plugin_paths_from_arg(const char *arg)
                }
        }
 
-       goto end;
-
+       return BT_VALUE_STATUS_OK;
 error:
-       BT_PUT(plugin_paths);
-
-end:
-       return plugin_paths;
+       return BT_VALUE_STATUS_ERROR;
 }
 
 /*
@@ -1066,6 +1068,24 @@ GScanner *create_csv_identifiers_scanner(void)
        return g_scanner_new(&scanner_config);
 }
 
+/*
+ * Inserts a string (if exists and not empty) or null to a map value
+ * object.
+ */
+static
+enum bt_value_status map_insert_string_or_null(struct bt_value *map,
+               const char *key, GString *string)
+{
+       enum bt_value_status ret;
+
+       if (string && string->len > 0) {
+               ret = bt_value_map_insert_string(map, key, string->str);
+       } else {
+               ret = bt_value_map_insert(map, key, bt_value_null);
+       }
+       return ret;
+}
+
 /*
  * Converts a comma-delimited list of known names (--names option) to
  * an array value object containing those names as string value objects.
@@ -1077,6 +1097,7 @@ struct bt_value *names_from_arg(const char *arg)
 {
        GScanner *scanner = NULL;
        struct bt_value *names = NULL;
+       bool found_all = false, found_none = false, found_item = false;
 
        names = bt_value_array_create();
        if (!names) {
@@ -1103,42 +1124,39 @@ struct bt_value *names_from_arg(const char *arg)
                        if (!strcmp(identifier, "payload") ||
                                        !strcmp(identifier, "args") ||
                                        !strcmp(identifier, "arg")) {
+                               found_item = true;
                                if (bt_value_array_append_string(names,
                                                "payload")) {
                                        goto error;
                                }
                        } else if (!strcmp(identifier, "context") ||
                                        !strcmp(identifier, "ctx")) {
+                               found_item = true;
                                if (bt_value_array_append_string(names,
                                                "context")) {
                                        goto error;
                                }
                        } else if (!strcmp(identifier, "scope") ||
                                        !strcmp(identifier, "header")) {
+                               found_item = true;
                                if (bt_value_array_append_string(names,
                                                identifier)) {
                                        goto error;
                                }
-                       } else if (!strcmp(identifier, "all") ||
-                                       !strcmp(identifier, "none")) {
-                               /*
-                                * "all" and "none" override all the
-                                * specific names.
-                                */
-                               BT_PUT(names);
-                               names = bt_value_array_create();
-                               if (!names) {
-                                       print_err_oom();
+                       } else if (!strcmp(identifier, "all")) {
+                               found_all = true;
+                               if (bt_value_array_append_string(names,
+                                               identifier)) {
                                        goto error;
                                }
-
+                       } else if (!strcmp(identifier, "none")) {
+                               found_none = true;
                                if (bt_value_array_append_string(names,
                                                identifier)) {
                                        goto error;
                                }
-                               goto end;
                        } else {
-                               printf_err("Unknown field name: \"%s\"\n",
+                               printf_err("Unknown field name: `%s`\n",
                                        identifier);
                                goto error;
                        }
@@ -1153,12 +1171,27 @@ struct bt_value *names_from_arg(const char *arg)
                }
        }
 
-       goto end;
+end:
+       if (found_none && found_all) {
+               printf_err("Only either `all` or `none` can be specified in the list given to the --names option, but not both.\n");
+               goto error;
+       }
+       /*
+        * Legacy behavior is to clear the defaults (show none) when at
+        * least one item is specified.
+        */
+       if (found_item && !found_none && !found_all) {
+               if (bt_value_array_append_string(names, "none")) {
+                       goto error;
+               }
+       }
+       if (scanner) {
+               g_scanner_destroy(scanner);
+       }
+       return names;
 
 error:
        BT_PUT(names);
-
-end:
        if (scanner) {
                g_scanner_destroy(scanner);
        }
@@ -1208,27 +1241,14 @@ struct bt_value *fields_from_arg(const char *arg)
                                        !strcmp(identifier, "trace:vpid") ||
                                        !strcmp(identifier, "loglevel") ||
                                        !strcmp(identifier, "emf") ||
-                                       !strcmp(identifier, "callsite")) {
+                                       !strcmp(identifier, "callsite") ||
+                                       !strcmp(identifier, "all")) {
                                if (bt_value_array_append_string(fields,
                                                identifier)) {
                                        goto error;
                                }
-                       } else if (!strcmp(identifier, "all")) {
-                               /* "all" override all the specific fields */
-                               BT_PUT(fields);
-                               fields = bt_value_array_create();
-                               if (!fields) {
-                                       print_err_oom();
-                                       goto error;
-                               }
-
-                               if (bt_value_array_append_string(fields,
-                                               identifier)) {
-                                       goto error;
-                               }
-                               goto end;
                        } else {
-                               printf_err("Unknown field name: \"%s\"\n",
+                               printf_err("Unknown field name: `%s`\n",
                                        identifier);
                                goto error;
                        }
@@ -1265,7 +1285,7 @@ int insert_flat_names_fields_from_array(struct bt_value *map_obj,
 {
        int ret = 0;
        int i;
-       GString *tmpstr = NULL;
+       GString *tmpstr = NULL, *default_value = NULL;
 
        /*
         * array_obj may be NULL if no CLI options were specified to
@@ -1282,9 +1302,17 @@ int insert_flat_names_fields_from_array(struct bt_value *map_obj,
                goto end;
        }
 
+       default_value = g_string_new(NULL);
+       if (!default_value) {
+               print_err_oom();
+               ret = -1;
+               goto end;
+       }
+
        for (i = 0; i < bt_value_array_size(array_obj); i++) {
                struct bt_value *str_obj = bt_value_array_get(array_obj, i);
                const char *suffix;
+               bool is_default = false;
 
                if (!str_obj) {
                        printf_err("Unexpected error\n");
@@ -1301,15 +1329,39 @@ int insert_flat_names_fields_from_array(struct bt_value *map_obj,
 
                g_string_assign(tmpstr, prefix);
                g_string_append(tmpstr, "-");
-               g_string_append(tmpstr, suffix);
-               ret = bt_value_map_insert_bool(map_obj, tmpstr->str, true);
-               if (ret) {
-                       print_err_oom();
-                       goto end;
+
+               /* Special-case for "all" and "none". */
+               if (!strcmp(suffix, "all")) {
+                       is_default = true;
+                       g_string_assign(default_value, "show");
+               } else if (!strcmp(suffix, "none")) {
+                       is_default = true;
+                       g_string_assign(default_value, "hide");
+               }
+               if (is_default) {
+                       g_string_append(tmpstr, "default");
+                       ret = map_insert_string_or_null(map_obj,
+                                       tmpstr->str,
+                                       default_value);
+                       if (ret) {
+                               print_err_oom();
+                               goto end;
+                       }
+               } else {
+                       g_string_append(tmpstr, suffix);
+                       ret = bt_value_map_insert_bool(map_obj, tmpstr->str,
+                                       true);
+                       if (ret) {
+                               print_err_oom();
+                               goto end;
+                       }
                }
        }
 
 end:
+       if (default_value) {
+               g_string_free(default_value, TRUE);
+       }
        if (tmpstr) {
                g_string_free(tmpstr, TRUE);
        }
@@ -1317,24 +1369,6 @@ end:
        return ret;
 }
 
-/*
- * Inserts a string (if exists and not empty) or null to a map value
- * object.
- */
-static
-enum bt_value_status map_insert_string_or_null(struct bt_value *map,
-               const char *key, GString *string)
-{
-       enum bt_value_status ret;
-
-       if (string && string->len > 0) {
-               ret = bt_value_map_insert_string(map, key, string->str);
-       } else {
-               ret = bt_value_map_insert(map, key, bt_value_null);
-       }
-       return ret;
-}
-
 /*
  * Returns the parameters (map value object) corresponding to the
  * legacy text format options.
@@ -1475,11 +1509,13 @@ int append_sinks_from_legacy_opts(GPtrArray *sinks,
 
        /* Create a component configuration */
        bt_config_component = bt_config_component_create(plugin_name,
-               component_name, params);
+               component_name);
        if (!bt_config_component) {
                goto error;
        }
 
+       BT_MOVE(bt_config_component->params, params);
+
        /* Move created component configuration to the array */
        g_ptr_array_add(sinks, bt_config_component);
 
@@ -1602,18 +1638,19 @@ int append_sources_from_legacy_opts(GPtrArray *sources,
 
                /* Create a component configuration */
                bt_config_component = bt_config_component_create("ctf",
-                       component_name, params);
+                       component_name);
                if (!bt_config_component) {
                        goto error;
                }
 
+               BT_MOVE(bt_config_component->params, params);
+
                /* Move created component configuration to the array */
                g_ptr_array_add(sources, bt_config_component);
 
                /* Put current stuff */
                BT_PUT(input_path);
                BT_PUT(input_path_copy);
-               BT_PUT(params);
        }
 
        goto end;
@@ -1788,9 +1825,9 @@ void print_output_legacy_to_sinks(
                assert(false);
        }
 
-       printf_err("Both \"%s\" legacy output format and non-legacy sink(s) specified.\n\n",
+       printf_err("Both `%s` legacy output format and non-legacy sink component\ninstances(s) specified.\n\n",
                input_format);
-       printf_err("Specify the following non-legacy sink instead of the legacy \"%s\"\noutput format options:\n\n",
+       printf_err("Specify the following non-legacy sink component instance instead of the\nlegacy `%s` output format options:\n\n",
                input_format);
        g_string_append(str, "-o ");
 
@@ -1812,7 +1849,7 @@ void print_output_legacy_to_sinks(
                        text_legacy_opts_is_any_set(text_legacy_opts)) {
                int ret;
 
-               g_string_append(str, ":'");
+               g_string_append(str, " -p '");
 
                if (g_string_append_string_path_param(str, "output-path",
                                text_legacy_opts->output)) {
@@ -1899,9 +1936,9 @@ void print_input_legacy_to_sources(enum legacy_input_format legacy_input_format,
                assert(false);
        }
 
-       printf_err("Both \"%s\" legacy input format and non-legacy source(s) specified.\n\n",
+       printf_err("Both `%s` legacy input format and non-legacy source component\ninstance(s) specified.\n\n",
                input_format);
-       printf_err("Specify the following non-legacy source(s) instead of the legacy \"%s\"\ninput format options and positional arguments:\n\n",
+       printf_err("Specify the following non-legacy source component instance(s) instead of the\nlegacy `%s` input format options and positional arguments:\n\n",
                input_format);
 
        for (i = 0; i < bt_value_array_size(legacy_input_paths); i++) {
@@ -1925,10 +1962,10 @@ void print_input_legacy_to_sources(enum legacy_input_format legacy_input_format,
 
                switch (legacy_input_format) {
                case LEGACY_INPUT_FORMAT_CTF:
-                       g_string_append(str, "fs:'path=\"");
+                       g_string_append(str, "fs -p 'path=\"");
                        break;
                case LEGACY_INPUT_FORMAT_LTTNG_LIVE:
-                       g_string_append(str, "lttng-live:'url=\"");
+                       g_string_append(str, "lttng-live -p 'url=\"");
                        break;
                default:
                        assert(false);
@@ -1975,14 +2012,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;
        }
@@ -1997,10 +2032,10 @@ bool validate_cfg(struct bt_config *cfg,
                if (bt_value_array_is_empty(legacy_input_paths)) {
                        switch (*legacy_input_format) {
                        case LEGACY_INPUT_FORMAT_CTF:
-                               printf_err("No input path specified for legacy \"ctf\" input format\n");
+                               printf_err("No input path specified for legacy `ctf` input format\n");
                                break;
                        case LEGACY_INPUT_FORMAT_LTTNG_LIVE:
-                               printf_err("No URL specified for legacy \"lttng-live\" input format\n");
+                               printf_err("No URL specified for legacy `lttng-live` input format\n");
                                break;
                        default:
                                assert(false);
@@ -2032,7 +2067,7 @@ bool validate_cfg(struct bt_config *cfg,
                if (text_legacy_opts_is_any_set(text_legacy_opts) &&
                                *legacy_output_format !=
                                LEGACY_OUTPUT_FORMAT_TEXT) {
-                       printf_err("Options for legacy \"text\" output format specified with a different legacy output format\n");
+                       printf_err("Options for legacy `text` output format specified with a different legacy output format\n");
                        goto error;
                }
 
@@ -2050,7 +2085,7 @@ bool validate_cfg(struct bt_config *cfg,
         */
        if (*legacy_output_format == LEGACY_OUTPUT_FORMAT_CTF_METADATA &&
                        *legacy_input_format != LEGACY_INPUT_FORMAT_CTF) {
-               printf_err("Legacy \"ctf-metadata\" output format requires using legacy \"ctf\" input format\n");
+               printf_err("Legacy `ctf-metadata` output format requires using legacy `ctf` input format\n");
                goto error;
        }
 
@@ -2082,6 +2117,8 @@ int parse_int64(const char *arg, int64_t *val)
 /* popt options */
 enum {
        OPT_NONE = 0,
+       OPT_BASE_PARAMS,
+       OPT_BEGIN,
        OPT_CLOCK_CYCLES,
        OPT_CLOCK_DATE,
        OPT_CLOCK_FORCE_CORRELATE,
@@ -2093,6 +2130,7 @@ enum {
        OPT_DEBUG_INFO_DIR,
        OPT_DEBUG_INFO_FULL_PATH,
        OPT_DEBUG_INFO_TARGET_PREFIX,
+       OPT_END,
        OPT_FIELDS,
        OPT_HELP,
        OPT_HELP_LEGACY,
@@ -2102,17 +2140,25 @@ enum {
        OPT_NO_DELTA,
        OPT_OUTPUT_FORMAT,
        OPT_OUTPUT_PATH,
+       OPT_PATH,
+       OPT_PARAMS,
        OPT_PLUGIN_PATH,
+       OPT_RESET_BASE_PARAMS,
        OPT_SINK,
        OPT_SOURCE,
        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 },
@@ -2124,6 +2170,7 @@ static struct poptOption long_options[] = {
        { "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 },
@@ -2133,12 +2180,18 @@ static struct poptOption long_options[] = {
        { "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 },
-       { "plugin-path", 'p', POPT_ARG_STRING, NULL, OPT_PLUGIN_PATH, 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 },
 };
 
@@ -2151,6 +2204,149 @@ static void set_offset_value(struct offset_opt *offset_opt, int64_t value)
        offset_opt->is_set = true;
 }
 
+enum bt_config_component_dest {
+       BT_CONFIG_COMPONENT_DEST_SOURCE,
+       BT_CONFIG_COMPONENT_DEST_SINK,
+};
+
+/*
+ * Adds a configuration component to the appropriate configuration
+ * array depending on the destination.
+ */
+static void add_cfg_comp(struct bt_config *cfg,
+               struct bt_config_component *cfg_comp,
+               enum bt_config_component_dest dest)
+{
+       if (dest == BT_CONFIG_COMPONENT_DEST_SOURCE) {
+               g_ptr_array_add(cfg->sources, cfg_comp);
+       } else {
+               g_ptr_array_add(cfg->sinks, cfg_comp);
+       }
+}
+
+static int split_timerange(const char *arg, const char **begin, const char **end)
+{
+       const char *c;
+
+       /* Try to match [begin,end] */
+       c = strchr(arg, '[');
+       if (!c)
+               goto skip;
+       *begin = ++c;
+       c = strchr(c, ',');
+       if (!c)
+               goto skip;
+       *end = ++c;
+       c = strchr(c, ']');
+       if (!c)
+               goto skip;
+       goto found;
+
+skip:
+       /* Try to match begin,end */
+       c = arg;
+       *begin = c;
+       c = strchr(c, ',');
+       if (!c)
+               goto not_found;
+       *end = ++c;
+       /* fall-through */
+found:
+       return 0;
+not_found:
+       return -1;
+}
+
+static char *bt_secure_getenv(const char *name)
+{
+       if (is_setuid_setgid()) {
+               printf_err("Disregarding %s environment variable for setuid/setgid binary", name);
+               return NULL;
+       }
+       return getenv(name);
+}
+
+static const char *get_home_dir(void)
+{
+       char *val = NULL;
+       struct passwd *pwd;
+
+       val = bt_secure_getenv(HOME_ENV_VAR);
+       if (val) {
+               goto end;
+       }
+       /* Fallback on password file. */
+       pwd = getpwuid(getuid());
+       if (!pwd) {
+               goto end;
+       }
+       val = pwd->pw_dir;
+end:
+       return val;
+}
+
+static int add_internal_plugin_paths(struct bt_config *cfg)
+{
+       if (!omit_home_plugin_path) {
+               char path[PATH_MAX];
+               const char *home_dir;
+
+               if (is_setuid_setgid()) {
+                       printf_debug("Skipping non-system plugin paths for setuid/setgid binary.");
+               } else {
+                       home_dir = get_home_dir();
+                       if (home_dir) {
+                               if (strlen(home_dir) + strlen(HOME_SUBPATH) + 1
+                                               >= PATH_MAX) {
+                                       printf_err("Home directory path too long\n");
+                                       goto error;
+                               }
+                               strcpy(path, home_dir);
+                               strcat(path, HOME_SUBPATH);
+                               if (plugin_paths_from_arg(cfg->plugin_paths, path)) {
+                                       printf_err("Invalid home plugin path\n");
+                                       goto error;
+                               }
+                       }
+               }
+       }
+
+       if (!omit_system_plugin_path) {
+               if (plugin_paths_from_arg(cfg->plugin_paths,
+                               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;
+}
+
 /*
  * Returns a Babeltrace configuration, out of command-line arguments,
  * containing everything that is needed to instanciate specific
@@ -2161,26 +2357,30 @@ static void set_offset_value(struct offset_opt *offset_opt, int64_t value)
  *
  * Return value is NULL on error, otherwise it's owned by the caller.
  */
-struct bt_config *bt_config_from_args(int argc, char *argv[], int *exit_code)
+struct bt_config *bt_config_from_args(int argc, const char *argv[], int *exit_code)
 {
        struct bt_config *cfg = NULL;
        poptContext pc = NULL;
        char *arg = NULL;
-       struct ctf_legacy_opts ctf_legacy_opts = { 0 };
-       struct text_legacy_opts text_legacy_opts = { 0 };
+       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;
-       int opt;
-
+       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, nr_omit_opt = 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) {
                print_err_oom();
@@ -2199,6 +2399,12 @@ struct bt_config *bt_config_from_args(int argc, char *argv[], int *exit_code)
                goto error;
        }
 
+       cur_base_params = bt_value_map_create();
+       if (!cur_base_params) {
+               print_err_oom();
+               goto error;
+       }
+
        /* Create config */
        cfg = g_new0(struct bt_config, 1);
        if (!cfg) {
@@ -2225,6 +2431,23 @@ struct bt_config *bt_config_from_args(int argc, char *argv[], int *exit_code)
                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);
+       }
+
+       cfg->plugin_paths = bt_value_array_create();
+       if (!cfg->plugin_paths) {
+               print_err_oom();
+               goto error;
+       }
+
        /* Parse options */
        pc = poptGetContext(NULL, argc, (const char **) argv, long_options, 0);
        if (!pc) {
@@ -2239,17 +2462,23 @@ struct bt_config *bt_config_from_args(int argc, char *argv[], int *exit_code)
 
                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:
+                       omit_system_plugin_path = true;
+                       nr_omit_opt += 2;
+                       break;
+               case OPT_OMIT_HOME_PLUGIN_PATH:
+                       omit_home_plugin_path = true;
+                       nr_omit_opt += 2;
+                       break;
                case OPT_OUTPUT_PATH:
                        if (text_legacy_opts.output->len > 0) {
                                printf_err("Duplicate --output option\n");
@@ -2277,8 +2506,6 @@ struct bt_config *bt_config_from_args(int argc, char *argv[], int *exit_code)
                case OPT_INPUT_FORMAT:
                case OPT_SOURCE:
                {
-                       struct bt_config_component *bt_config_component;
-
                        if (opt == OPT_INPUT_FORMAT) {
                                if (!strcmp(arg, "ctf")) {
                                        /* Legacy CTF input format */
@@ -2303,22 +2530,36 @@ struct bt_config *bt_config_from_args(int argc, char *argv[], int *exit_code)
                                }
                        }
 
+                       use_implicit_source = false;
+
                        /* Non-legacy: try to create a component config */
-                       bt_config_component = bt_config_component_from_arg(arg);
-                       if (!bt_config_component) {
-                               printf_err("Invalid source component format:\n    %s\n",
+                       if (cur_cfg_comp && !cur_is_implicit_source) {
+                               add_cfg_comp(cfg, cur_cfg_comp,
+                                       cur_cfg_comp_dest);
+                       }
+
+                       cur_cfg_comp = bt_config_component_from_arg(arg);
+                       if (!cur_cfg_comp) {
+                               printf_err("Invalid format for --source option's argument:\n    %s\n",
                                        arg);
                                goto error;
                        }
+                       cur_is_implicit_source = false;
 
-                       g_ptr_array_add(cfg->sources, bt_config_component);
+                       assert(cur_base_params);
+                       bt_put(cur_cfg_comp->params);
+                       cur_cfg_comp->params = bt_value_copy(cur_base_params);
+                       if (!cur_cfg_comp->params) {
+                               print_err_oom();
+                               goto end;
+                       }
+
+                       cur_cfg_comp_dest = BT_CONFIG_COMPONENT_DEST_SOURCE;
                        break;
                }
                case OPT_OUTPUT_FORMAT:
                case OPT_SINK:
                {
-                       struct bt_config_component *bt_config_component;
-
                        if (opt == OPT_OUTPUT_FORMAT) {
                                if (!strcmp(arg, "text")) {
                                        /* Legacy CTF-text output format */
@@ -2354,16 +2595,96 @@ struct bt_config *bt_config_from_args(int argc, char *argv[], int *exit_code)
                        }
 
                        /* Non-legacy: try to create a component config */
-                       bt_config_component = bt_config_component_from_arg(arg);
-                       if (!bt_config_component) {
-                               printf_err("Invalid sink component format:\n    %s\n",
+                       if (cur_cfg_comp && !cur_is_implicit_source) {
+                               add_cfg_comp(cfg, cur_cfg_comp,
+                                       cur_cfg_comp_dest);
+                       }
+
+                       cur_cfg_comp = bt_config_component_from_arg(arg);
+                       if (!cur_cfg_comp) {
+                               printf_err("Invalid format for --sink option's argument:\n    %s\n",
+                                       arg);
+                               goto error;
+                       }
+                       cur_is_implicit_source = false;
+
+                       assert(cur_base_params);
+                       bt_put(cur_cfg_comp->params);
+                       cur_cfg_comp->params = bt_value_copy(cur_base_params);
+                       if (!cur_cfg_comp->params) {
+                               print_err_oom();
+                               goto end;
+                       }
+
+                       cur_cfg_comp_dest = BT_CONFIG_COMPONENT_DEST_SINK;
+                       break;
+               }
+               case OPT_PARAMS:
+               {
+                       struct bt_value *params;
+                       struct bt_value *params_to_set;
+
+                       if (!cur_cfg_comp) {
+                               printf_err("Can not apply parameter to unavailable default source component \"%s\".\n",
+                                       DEFAULT_SOURCE_COMPONENT_NAME);
+                               goto error;
+                       }
+
+                       params = bt_value_from_arg(arg);
+                       if (!params) {
+                               printf_err("Invalid format for --params option's argument:\n    %s\n",
+                                       arg);
+                               goto error;
+                       }
+
+                       params_to_set = bt_value_map_extend(cur_cfg_comp->params,
+                               params);
+                       BT_PUT(params);
+                       if (!params_to_set) {
+                               printf_err("Cannot extend current component parameters with --params option's argument:\n    %s\n",
                                        arg);
                                goto error;
                        }
 
-                       g_ptr_array_add(cfg->sinks, bt_config_component);
+                       BT_MOVE(cur_cfg_comp->params, params_to_set);
                        break;
                }
+               case OPT_PATH:
+                       if (!cur_cfg_comp) {
+                               printf_err("Can not apply parameter to unavailable default source component \"%s\".\n",
+                                       DEFAULT_SOURCE_COMPONENT_NAME);
+                               goto error;
+                       }
+
+                       assert(cur_cfg_comp->params);
+
+                       if (bt_value_map_insert_string(cur_cfg_comp->params,
+                                       "path", arg)) {
+                               print_err_oom();
+                               goto error;
+                       }
+                       break;
+               case OPT_BASE_PARAMS:
+               {
+                       struct bt_value *params = bt_value_from_arg(arg);
+
+                       if (!params) {
+                               printf_err("Invalid format for --base-params option's argument:\n    %s\n",
+                                       arg);
+                               goto error;
+                       }
+
+                       BT_MOVE(cur_base_params, params);
+                       break;
+               }
+               case OPT_RESET_BASE_PARAMS:
+                       BT_PUT(cur_base_params);
+                       cur_base_params = bt_value_map_create();
+                       if (!cur_base_params) {
+                               print_err_oom();
+                               goto error;
+                       }
+                       break;
                case OPT_NAMES:
                        if (text_legacy_opts.names) {
                                printf_err("Duplicate --names option\n");
@@ -2446,6 +2767,67 @@ struct bt_config *bt_config_from_args(int argc, char *argv[], int *exit_code)
                case OPT_CLOCK_FORCE_CORRELATE:
                        cfg->force_correlate = true;
                        break;
+               case OPT_BEGIN:
+                       if (!cur_cfg_comp) {
+                               printf_err("Can not apply parameter to unavailable default source component \"%s\".\n",
+                                       DEFAULT_SOURCE_COMPONENT_NAME);
+                               goto error;
+                       }
+                       if (cur_cfg_comp_dest != BT_CONFIG_COMPONENT_DEST_SOURCE) {
+                               printf_err("--begin option must follow a --source option\n");
+                               goto error;
+                       }
+                       if (bt_value_map_insert_string(cur_cfg_comp->params,
+                                       "begin", arg)) {
+                               print_err_oom();
+                               goto error;
+                       }
+                       break;
+               case OPT_END:
+                       if (!cur_cfg_comp) {
+                               printf_err("Can not apply parameter to unavailable default source component \"%s\".\n",
+                                       DEFAULT_SOURCE_COMPONENT_NAME);
+                               goto error;
+                       }
+                       if (cur_cfg_comp_dest != BT_CONFIG_COMPONENT_DEST_SOURCE) {
+                               printf_err("--end option must follow a --source option\n");
+                               goto error;
+                       }
+                       if (bt_value_map_insert_string(cur_cfg_comp->params,
+                                       "end", arg)) {
+                               print_err_oom();
+                               goto error;
+                       }
+                       break;
+               case OPT_TIMERANGE:
+               {
+                       const char *begin, *end;
+
+                       if (!cur_cfg_comp) {
+                               printf_err("Can not apply parameter to unavailable default source component \"%s\".\n",
+                                       DEFAULT_SOURCE_COMPONENT_NAME);
+                               goto error;
+                       }
+                       if (cur_cfg_comp_dest != BT_CONFIG_COMPONENT_DEST_SOURCE) {
+                               printf_err("--timerange option must follow a --source option\n");
+                               goto error;
+                       }
+                       if (split_timerange(arg, &begin, &end)) {
+                               printf_err("Invalid --timerange format, expecting: begin,end or [begin,end] (where [] are actual brackets)\n");
+                               goto error;
+                       }
+                       if (bt_value_map_insert_string(cur_cfg_comp->params,
+                                       "begin", begin)) {
+                               print_err_oom();
+                               goto error;
+                       }
+                       if (bt_value_map_insert_string(cur_cfg_comp->params,
+                                       "end", end)) {
+                               print_err_oom();
+                               goto error;
+                       }
+                       break;
+               }
                case OPT_HELP:
                        BT_PUT(cfg);
                        print_usage(stdout);
@@ -2477,6 +2859,11 @@ struct bt_config *bt_config_from_args(int argc, char *argv[], int *exit_code)
                arg = NULL;
        }
 
+       if (argc - nr_omit_opt <= 1) {
+               print_usage(stdout);
+               goto put_cfg;
+       }
+
        /* Check for option parsing error */
        if (opt < -1) {
                printf_err("While parsing command-line options, at option %s: %s\n",
@@ -2499,6 +2886,16 @@ struct bt_config *bt_config_from_args(int argc, char *argv[], int *exit_code)
                }
        }
 
+       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,
@@ -2515,9 +2912,27 @@ struct bt_config *bt_config_from_args(int argc, char *argv[], int *exit_code)
                if (append_sources_from_legacy_opts(cfg->sources,
                                legacy_input_format, &ctf_legacy_opts,
                                legacy_input_paths)) {
-                       printf_err("Cannot convert legacy input format options to source(s)\n");
+                       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;
+                       }
+               }
        }
 
        /*
@@ -2527,18 +2942,30 @@ struct bt_config *bt_config_from_args(int argc, char *argv[], int *exit_code)
        if (legacy_output_format) {
                if (append_sinks_from_legacy_opts(cfg->sinks,
                                legacy_output_format, &text_legacy_opts)) {
-                       printf_err("Cannot convert legacy output format options to sink(s)\n");
+                       printf_err("Cannot convert legacy output format options to sink component instance(s)\n");
                        goto error;
                }
        }
 
+       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:
+       *exit_code = 1;
+put_cfg:
        BT_PUT(cfg);
        cfg = NULL;
-       *exit_code = 1;
-
 end:
        if (pc) {
                poptFreeContext(pc);
@@ -2557,6 +2984,9 @@ end:
        }
 
        free(arg);
+       BT_PUT(implicit_source_comp);
+       BT_PUT(cur_cfg_comp);
+       BT_PUT(cur_base_params);
        BT_PUT(text_legacy_opts.names);
        BT_PUT(text_legacy_opts.fields);
        BT_PUT(legacy_input_paths);
This page took 0.042379 seconds and 4 git commands to generate.