diff options
author | Ryszard Knop <ryszard.knop@intel.com> | 2022-08-08 16:58:09 +0200 |
---|---|---|
committer | Ryszard Knop <ryszard.knop@intel.com> | 2022-08-31 13:05:12 +0200 |
commit | 66ee80cc5854a4c187c9751f7bf36e5e88f8e994 (patch) | |
tree | 172bcfdd8ca45c45c7fe7026606e8f2019332df1 /runner | |
parent | 01737c4a45773285cd9df6ff8566c3d22216a0b0 (diff) |
runner: Add the --environment flag
Allows specifying additional environment variables to be set for the
launched test processes. This commit introduces the argument parsing.
v2:
- Moved warning fixes from later commits here
- igt_list_empty_or_null -> igt_list_empty (Mauro)
- Optimized the parser, more error handling (Mauro)
Diffstat (limited to 'runner')
-rw-r--r-- | runner/settings.c | 123 | ||||
-rw-r--r-- | runner/settings.h | 9 |
2 files changed, 131 insertions, 1 deletions
diff --git a/runner/settings.c b/runner/settings.c index ba2880437..d0f642a42 100644 --- a/runner/settings.c +++ b/runner/settings.c @@ -35,6 +35,7 @@ enum { OPT_DRY_RUN = 'd', OPT_INCLUDE = 't', OPT_EXCLUDE = 'x', + OPT_ENVIRONMENT = 'e', OPT_SYNC = 's', OPT_LOG_LEVEL = 'l', OPT_OVERWRITE = 'o', @@ -390,6 +391,119 @@ static void free_regexes(struct regex_list *regexes) free(regexes->regexes); } +/** + * string_trim_and_duplicate() - returns a duplicated, trimmed string + * @string: string to trim and duplicate + * + * If the provided string is NULL, a NULL is returned. In any other case, a + * newly-allocated string of length up to strlen(string) is returned. The + * returned string has its whitespace removed (as detected by isspace), while + * the original string is left unmodified. + */ +static char *string_trim_and_duplicate(const char *string) { + size_t length; + + if (string == NULL) + return NULL; + + length = strlen(string); + + while (length > 0 && isspace(string[0])) { + string++; + length--; + } + + while (length > 0 && isspace(string[length - 1])) { + length--; + } + + return strndup(string, length); +} + +/** + * add_env_var() - Adds a new environment variable to the runner settings. + * @env_vars: Pointer to the env var list head from the settings. + * @key_value: Environment variable key-value pair string to add. + * + * key_value must be a string like "KEY=VALUE" or just "KEY" if the value is to + * be loaded from the runner's environment variables. In the latter case, if + * the requested variable is not set, the operation will fail. + * + * An empty variable may be set by providing an key_value of "KEY=" or setting + * an empty variable for the runner process, then providing just the "KEY". + */ +static bool add_env_var(struct igt_list_head *env_vars, const char *key_value) { + char *env_kv, *value_str; + struct environment_variable *var = NULL; + + if (env_vars == NULL || key_value == NULL || strlen(key_value) == 0) + goto error; + + env_kv = strdup(key_value); + value_str = strpbrk(env_kv, "\n="); + + if (value_str == env_kv) { + fprintf(stderr, "Missing key for --environment \"%s\"\n", key_value); + goto error; + } + + if (value_str != NULL && value_str[0] != '=') { + fprintf(stderr, "Invalid characters in key for --environment \"%s\"\n", key_value); + goto error; + } + + if (value_str != NULL) { + /* value provided - copy string contents after '=' */ + value_str[0] = '\0'; + value_str++; + } else { + /* env_kv is the key - use the runner's environment, if set */ + value_str = getenv(env_kv); + if (value_str == NULL) { + fprintf(stderr, "No value provided for --environment \"%s\" and " + "variable is not set for igt_runner\n", env_kv); + goto error; + } + } + + var = malloc(sizeof(struct environment_variable)); + + var->key = string_trim_and_duplicate(env_kv); + if (strlen(var->key) == 0) { + fprintf(stderr, "Environment variable key is empty for \"%s\"\n", key_value); + goto error; + } + + var->value = strdup(value_str); /* Can be empty, that's okay */ + + igt_list_add_tail(&var->link, env_vars); + free(env_kv); + return true; + +error: + if (var != NULL) + free(var); + + if (env_kv != NULL) + free(env_kv); + + return false; +} + +static void free_env_vars(struct igt_list_head *env_vars) { + struct environment_variable *iter; + + while (!igt_list_empty(env_vars)) { + iter = igt_list_first_entry(env_vars, iter, link); + + free(iter->key); + free(iter->value); + + igt_list_del(&iter->link); + free(iter); + } +} + static bool readable_file(const char *filename) { return !access(filename, R_OK); @@ -486,6 +600,7 @@ static void print_version(void) void init_settings(struct settings *settings) { memset(settings, 0, sizeof(*settings)); + IGT_INIT_LIST_HEAD(&settings->env_vars); } void clear_settings(struct settings *settings) @@ -497,6 +612,7 @@ void clear_settings(struct settings *settings) free_regexes(&settings->include_regexes); free_regexes(&settings->exclude_regexes); + free_env_vars(&settings->env_vars); init_settings(settings); } @@ -515,6 +631,7 @@ bool parse_options(int argc, char **argv, {"allow-non-root", no_argument, NULL, OPT_ALLOW_NON_ROOT}, {"include-tests", required_argument, NULL, OPT_INCLUDE}, {"exclude-tests", required_argument, NULL, OPT_EXCLUDE}, + {"environment", required_argument, NULL, OPT_ENVIRONMENT}, {"abort-on-monitored-error", optional_argument, NULL, OPT_ABORT_ON_ERROR}, {"disk-usage-limit", required_argument, NULL, OPT_DISK_USAGE_LIMIT}, {"sync", no_argument, NULL, OPT_SYNC}, @@ -544,7 +661,7 @@ bool parse_options(int argc, char **argv, settings->dmesg_warn_level = -1; - while ((c = getopt_long(argc, argv, "hn:dt:x:sl:omb:L", + while ((c = getopt_long(argc, argv, "hn:dt:x:e:sl:omb:L", long_options, NULL)) != -1) { switch (c) { case OPT_VERSION: @@ -570,6 +687,10 @@ bool parse_options(int argc, char **argv, if (!add_regex(&settings->exclude_regexes, strdup(optarg))) goto error; break; + case OPT_ENVIRONMENT: + if (!add_env_var(&settings->env_vars, optarg)) + goto error; + break; case OPT_ABORT_ON_ERROR: if (!parse_abort_conditions(settings, optarg)) goto error; diff --git a/runner/settings.h b/runner/settings.h index 6d444d012..819c34602 100644 --- a/runner/settings.h +++ b/runner/settings.h @@ -7,6 +7,8 @@ #include <stdio.h> #include <glib.h> +#include "igt_list.h" + enum { LOG_LEVEL_NORMAL = 0, LOG_LEVEL_QUIET = -1, @@ -37,6 +39,12 @@ struct regex_list { size_t size; }; +struct environment_variable { + struct igt_list_head link; + char * key; + char * value; +}; + struct settings { int abort_mask; size_t disk_usage_limit; @@ -46,6 +54,7 @@ struct settings { bool allow_non_root; struct regex_list include_regexes; struct regex_list exclude_regexes; + struct igt_list_head env_vars; bool sync; int log_level; bool overwrite; |