Compare commits

..

No commits in common. "e149ba1b1ff41459c573cbcc5b2512bb1e73dfae" and "f6358f893184e02306d96418b99a62a95c2b0d2a" have entirely different histories.

5 changed files with 49 additions and 45 deletions

View File

@ -1060,14 +1060,6 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
<refsect2> <refsect2>
<title>Environment Commands</title> <title>Environment Commands</title>
<para><command>systemd</command> supports an environment block that is passed to processes the manager
spawns. The names of the variables can contain ASCII letters, digits, and the underscore
character. Variable names cannot be empty or start with a digit. In variable values, most characters
are allowed, but non-printable characters are currently rejected. The total length of the environment
block is limited to <constant>_SC_ARG_MAX</constant> value defined by
<citerefentry project='man-pages'><refentrytitle>sysconf</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
</para>
<variablelist> <variablelist>
<varlistentry> <varlistentry>
<term><command>show-environment</command></term> <term><command>show-environment</command></term>
@ -1099,9 +1091,8 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
<term><command>set-environment <replaceable>VARIABLE=VALUE</replaceable></command></term> <term><command>set-environment <replaceable>VARIABLE=VALUE</replaceable></command></term>
<listitem> <listitem>
<para>Set one or more systemd manager environment variables, as specified on the command <para>Set one or more systemd manager environment variables,
line. This command will fail if variable names and values do not conform to the rules listed as specified on the command line.</para>
above.</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
@ -1122,11 +1113,13 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
</term> </term>
<listitem> <listitem>
<para>Import all, one or more environment variables set on the client into the systemd manager <para>Import all, one or more environment variables set on
environment block. If no arguments are passed, the entire environment block is imported. the client into the systemd manager environment block. If
Otherwise, a list of one or more environment variable names should be passed, whose client-side no arguments are passed, the entire environment block is
values are then imported into the manager's environment block. This command will silently ignore imported. Otherwise, a list of one or more environment
any assignments which do not conform to the rules listed above.</para> variable names should be passed, whose client-side values
are then imported into the manager's environment
block.</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
</variablelist> </variablelist>

View File

@ -2186,18 +2186,13 @@ SystemCallErrorNumber=EPERM</programlisting>
<varlistentry> <varlistentry>
<term><varname>Environment=</varname></term> <term><varname>Environment=</varname></term>
<listitem><para>Sets environment variables for executed processes. Takes a space-separated list of <listitem><para>Sets environment variables for executed processes. Takes a space-separated list of variable
variable assignments. This option may be specified more than once, in which case all listed variables assignments. This option may be specified more than once, in which case all listed variables will be set. If
will be set. If the same variable is set twice, the later setting will override the earlier the same variable is set twice, the later setting will override the earlier setting. If the empty string is
setting. If the empty string is assigned to this option, the list of environment variables is reset, assigned to this option, the list of environment variables is reset, all prior assignments have no
all prior assignments have no effect. Variable expansion is not performed inside the strings, effect. Variable expansion is not performed inside the strings, however, specifier expansion is possible. The $
however, specifier expansion is possible. The <literal>$</literal> character has no special character has no special meaning. If you need to assign a value containing spaces or the equals sign to a
meaning. If you need to assign a value containing spaces or the equals sign to a variable, use double variable, use double quotes (") for the assignment.</para>
quotes (") for the assignment.</para>
<para>The names of the variables can contain ASCII letters, digits, and the underscore
character. Variable names cannot be empty or start with a digit. In variable values, most characters
are allowed, but non-printable characters are currently rejected.</para>
<para>Example: <para>Example:
<programlisting>Environment="VAR1=word1 word2" VAR2=word3 "VAR3=$word 5 6"</programlisting> <programlisting>Environment="VAR1=word1 word2" VAR2=word3 "VAR3=$word 5 6"</programlisting>

View File

@ -21,18 +21,21 @@
DIGITS LETTERS \ DIGITS LETTERS \
"_" "_"
static bool env_name_is_valid_n(const char *e, size_t n) { static bool printable_portable_character(char c) {
const char *p; /* POSIX.1-2008 specifies almost all ASCII characters as "portable". (Only DEL is excluded, and
* additionally NUL and = are not allowed in variable names). We are stricter, and additionally
* reject BEL, BS, HT, CR, LF, VT, FF and SPACE, i.e. all whitespace. */
return c >= '!' && c <= '~';
}
static bool env_name_is_valid_n(const char *e, size_t n) {
if (!e) if (!e)
return false; return false;
if (n <= 0) if (n <= 0)
return false; return false;
if (e[0] >= '0' && e[0] <= '9')
return false;
/* POSIX says the overall size of the environment block cannot /* POSIX says the overall size of the environment block cannot
* be > ARG_MAX, an individual assignment hence cannot be * be > ARG_MAX, an individual assignment hence cannot be
* either. Discounting the equal sign and trailing NUL this * either. Discounting the equal sign and trailing NUL this
@ -41,15 +44,18 @@ static bool env_name_is_valid_n(const char *e, size_t n) {
if (n > (size_t) sysconf(_SC_ARG_MAX) - 2) if (n > (size_t) sysconf(_SC_ARG_MAX) - 2)
return false; return false;
for (p = e; p < e + n; p++) for (const char *p = e; p < e + n; p++)
if (!strchr(VALID_BASH_ENV_NAME_CHARS, *p)) if (!printable_portable_character(*p) || *p == '=')
return false; return false;
return true; return true;
} }
bool env_name_is_valid(const char *e) { bool env_name_is_valid(const char *e) {
return env_name_is_valid_n(e, strlen_ptr(e)); if (!e)
return false;
return env_name_is_valid_n(e, strlen(e));
} }
bool env_value_is_valid(const char *e) { bool env_value_is_valid(const char *e) {

View File

@ -274,10 +274,12 @@ static void test_env_clean(void) {
assert_se(streq(e[0], "FOOBAR=WALDO")); assert_se(streq(e[0], "FOOBAR=WALDO"));
assert_se(streq(e[1], "X=")); assert_se(streq(e[1], "X="));
assert_se(streq(e[2], "F=F")); assert_se(streq(e[2], "F=F"));
assert_se(streq(e[3], "abcd=äöüß")); assert_se(streq(e[3], "0000=000"));
assert_se(streq(e[4], "xyz=xyz\n")); assert_se(streq(e[4], "abcd=äöüß"));
assert_se(streq(e[5], "another=final one")); assert_se(streq(e[5], "xyz=xyz\n"));
assert_se(e[6] == NULL); assert_se(streq(e[6], "another=final one"));
assert_se(streq(e[7], "BASH_FUNC_foo%%=() { echo foo\n}"));
assert_se(e[8] == NULL);
} }
static void test_env_name_is_valid(void) { static void test_env_name_is_valid(void) {
@ -290,8 +292,11 @@ static void test_env_name_is_valid(void) {
assert_se(!env_name_is_valid("xxx\a")); assert_se(!env_name_is_valid("xxx\a"));
assert_se(!env_name_is_valid("xxx\007b")); assert_se(!env_name_is_valid("xxx\007b"));
assert_se(!env_name_is_valid("\007\009")); assert_se(!env_name_is_valid("\007\009"));
assert_se(!env_name_is_valid("5_starting_with_a_number_is_wrong")); assert_se( env_name_is_valid("5_starting_with_a_number_is_unexpected_but_valid"));
assert_se(!env_name_is_valid("#¤%&?_only_numbers_letters_and_underscore_allowed")); assert_se(!env_name_is_valid("#¤%&?_only_numbers_letters_and_underscore_allowed"));
assert_se( env_name_is_valid("BASH_FUNC_foo%%"));
assert_se(!env_name_is_valid("with spaces%%"));
assert_se(!env_name_is_valid("with\nnewline%%"));
} }
static void test_env_value_is_valid(void) { static void test_env_value_is_valid(void) {
@ -320,9 +325,13 @@ static void test_env_assignment_is_valid(void) {
assert_se(!env_assignment_is_valid("a b=")); assert_se(!env_assignment_is_valid("a b="));
assert_se(!env_assignment_is_valid("a =")); assert_se(!env_assignment_is_valid("a ="));
assert_se(!env_assignment_is_valid(" b=")); assert_se(!env_assignment_is_valid(" b="));
/* no dots or dashes: http://tldp.org/LDP/abs/html/gotchas.html */ /* Names with dots and dashes makes those variables inaccessible as bash variables (as the syntax
assert_se(!env_assignment_is_valid("a.b=")); * simply does not allow such variable names, see http://tldp.org/LDP/abs/html/gotchas.html). They
assert_se(!env_assignment_is_valid("a-b=")); * are still valid variables according to POSIX though. */
assert_se( env_assignment_is_valid("a.b="));
assert_se( env_assignment_is_valid("a-b="));
/* Those are not ASCII, so not valid according to POSIX (though zsh does allow unicode variable
* names). */
assert_se(!env_assignment_is_valid("\007=głąb kapuściany")); assert_se(!env_assignment_is_valid("\007=głąb kapuściany"));
assert_se(!env_assignment_is_valid("c\009=\007\009\011")); assert_se(!env_assignment_is_valid("c\009=\007\009\011"));
assert_se(!env_assignment_is_valid("głąb=printf \"\x1b]0;<mock-chroot>\x07<mock-chroot>\"")); assert_se(!env_assignment_is_valid("głąb=printf \"\x1b]0;<mock-chroot>\x07<mock-chroot>\""));

View File

@ -765,8 +765,9 @@ static void test_config_parse_pass_environ(void) {
"PassEnvironment", 0, "'invalid name' 'normal_name' A=1 'special_name$$' \\", "PassEnvironment", 0, "'invalid name' 'normal_name' A=1 'special_name$$' \\",
&passenv, NULL); &passenv, NULL);
assert_se(r >= 0); assert_se(r >= 0);
assert_se(strv_length(passenv) == 1); assert_se(strv_length(passenv) == 2);
assert_se(streq(passenv[0], "normal_name")); assert_se(streq(passenv[0], "normal_name"));
assert_se(streq(passenv[1], "special_name$$"));
} }
static void test_unit_dump_config_items(void) { static void test_unit_dump_config_items(void) {