In addition to parsing options, mu_parse_opts
supports parsing
environment variables as well. Environment variables are specified using
the env_var
field (see Option Structure). Values of
environment variables are specified in the same way as arguments are
specified to options (see Option Arguments).
Unlike options, environment variables are parsed in the program
environment (or the environment parameter to
mu_opt_context_new_with_env
), rather than in argv
(see Parsing Options and Environment). And unlike long options and
suboptions, environment variables may not be abbreviated. And
whereas an invalid option will cause an error, an invalid
environment variable will be ignored.
Environment variables may be specified for suboptions, and an
environment variable may take suboptions as a value as well. For
example, you might have an environment variable, ENV
, which takes
a suboption foo, which itself takes an optional string
argument, say. And suppose foo has an equivalent environment
variable, ENV_FOO
. Then you might specify a value ‘bar’ to
the foo suboption either by specifying a value to ENV
like this:
, or by specifying a value directly
to ENV
=foo=barENV_FOO
like this:
. The example shows
how to do this as well. See Parsing Suboptions for more information
on suboptions.
ENV_FOO
=bar
Environment variables are always parsed before command line options. Environment variables and long/short options may be specified in the same option, but if this is the case, the command line option(s) will take precedence over the environment variable, since the environment variables will always be parsed first.
If an environment variable has aliases (see Aliases for Options and Environment Variables), aliases
specified first will take precedence. For example, if an environment
variable is specified as ‘FOO|BAR’, and both FOO
and
BAR
are in the environment, then the value of FOO
will take
precedence because it was specified as an alias before BAR
. Note
also that if both FOO
and BAR
are specified in the
environment, the value of BAR
will be completely ignored. The
callback (if any) will only be called once, for FOO
(see Option Callbacks).
Another thing to note is that if you have an environment variable with a
has_arg
value of MU_OPT_NONE
, then if that environment
variable is encountered, and it has a value other than the empty string,
that will cause an error. This is not very user-friendly behavior, and
you might consider using a has_arg
of MU_OPT_OPTIONAL
and
an arg_type
of MU_OPT_BOOL
. Then, if the environment
variable has no value, you can default to true. This is more
user-friendly, because things like
or
ENV_VAR
=yes
will do what is expected (assuming your
environment variable is called ENV_VAR
=noENV_VAR
).
Traditionally, environment variable names are in ALL CAPS.
Here is an example of how environment variables can be parsed:
#include <stdio.h> #include <mu/options.h> #include <mu/safe.h> /* For mu_opt_context_x* */ /* Print a message when an option is found. */ int print_opt(int has_arg, const char *arg, void *data, char *err) { const char *name = data; printf("Found an option/environment variable '%s'", name); if (has_arg) printf(" with an argument '%s'", arg); putchar('\n'); return 0; } int main(int argc, char **argv) { int ret; const MU_OPT suboptions[] = { { .subopt_name = "subopt", /* Suboptions can have environment variables as well. */ .env_var = "ENV_SUBOPT", .has_arg = MU_OPT_OPTIONAL, .arg_type = MU_OPT_STRING, .callback_string = print_opt, .cb_data = "a suboption", .help = "a suboption with an equivalent environment variable" }, { 0 } }; const MU_OPT options[] = { { .short_opt = "a", .long_opt = "an-option", /* AN_ENV_VAR will always take precedence over ALIAS since it is specified first below. */ .env_var = "AN_ENV_VAR|ALIAS", .has_arg = MU_OPT_OPTIONAL, .arg_type = MU_OPT_STRING, .callback_string = print_opt, .cb_data = "an option", .help = "an option with an equivalent environment variable" }, { .short_opt = "b", .long_opt = "another-option", .has_arg = MU_OPT_OPTIONAL, .arg_type = MU_OPT_STRING, .callback_string = print_opt, .cb_data = "another option", .help = "an option without an equivalent environment variable" }, { .env_var = "ANOTHER_ENV_VAR", .has_arg = MU_OPT_REQUIRED, /* Environment variables can have suboptions as well. */ .arg_type = MU_OPT_SUBOPT, .subopts = suboptions, .help = "an environment variable (which takes " "suboptions) without an equivalent option" }, { 0 } }; MU_OPT_CONTEXT *context; context = mu_opt_context_xnew(argc, argv, options, MU_OPT_PERMUTE); /* Add the help option. */ mu_opt_context_add_help(context, NULL, NULL, "Parse options and environment variables.", NULL, "1", NULL, NULL, NULL); mu_opt_context_xadd_help_options(context, MU_HELP_BOTH); /* Parse the options. */ ret = mu_parse_opts(context); mu_opt_context_xfree(context); if (MU_OPT_ERR(ret)) return 1; return 0; }
And here is the output of the above program (note, the COLUMNS
environment variable is set to 65 so that the help message will look
good in this manual):
$ COLUMNS=65 $ export COLUMNS $ AN_ENV_VAR=foo ./environ --an-option=bar --another-option=baz -| Found an option/environment variable 'an option' with an argument 'foo' -| Found an option/environment variable 'an option' with an argument 'bar' -| Found an option/environment variable 'another option' with an argument 'baz' $ ANOTHER_ENV_VAR=subopt=foo ./environ -| Found an option/environment variable 'a suboption' with an argument 'foo' $ ENV_SUBOPT=foo ./environ -| Found an option/environment variable 'a suboption' with an argument 'foo' # AN_ENV_VAR will always take precedence over ALIAS. Also note that # the callback is only called once, even though both aliases are # specified. $ AN_ENV_VAR=foo ALIAS=bar ./environ -| Found an option/environment variable 'an option' with an argument 'foo' $ ALIAS=bar AN_ENV_VAR=foo ./environ -| Found an option/environment variable 'an option' with an argument 'foo' $ ./environ --help -| Usage: ./environ [OPTION]... -| Parse options and environment variables. -| -| -a, --an-option[=STRING] an option with an equivalent environment variable -| -b, --another-option[=STRING] an option without an equivalent environment variable -| -h, --help[=plain|man] print this help in plain text format if 'plain', or as a man(1) -| page if 'man'; if the argument is omitted, it will default to -| 'plain'. -| -| Suboptions for ANOTHER_ENV_VAR: -| subopt[=STRING] a suboption with an equivalent environment variable -| -| ENVIRONMENT -| -| AN_ENV_VAR, ALIAS[=STRING] an option with an equivalent environment variable -| ANOTHER_ENV_VAR=SUBOPTS an environment variable (which takes suboptions) without an -| equivalent option -| ENV_SUBOPT[=STRING] a suboption with an equivalent environment variable