Во многих Linux-системах /bin/sh
на самом деле /bin/dash
.
Как уже упоминалось в комментарии @MichaelHomer /bin/dash
будет очищать среду и удалять из нее любые строки, которые не имеют формы /^[a-zA-Z_][a-zA-Z_0-9]*=.*/
, включая BASH_FUNC_foo%%=...
, потому что %%
.
Это довольно специфично для dash
и для OpenBSDksh
(и mksh
, основанных на нем )--, другие оболочки не будут этим заниматься.
Пример в Debian, где /bin/sh
— этоdash
:
$ env - '@#%=' 'foo%%=bar' /bin/sh -c /usr/bin/printenv
PWD=/your/cwd
$ env - '@#%=' 'foo%%=bar' /usr/bin/printenv
@#%=
foo%%=bar
$ env - '@#%=' 'foo%%=bar' /bin/bash -c /usr/bin/printenv
[...]
@#%=
foo%%=bar
Для ссылки на источник вы можете посмотреть src/var.c в источнике dash
:
initvar();
for (envp = environ ; *envp ; envp++) {
p = endofname(*envp);
if (p != *envp && *p == '=') {
setvareq(*envp, VEXPORT|VTEXTFIXED);
}
}
Когда dash
exec является другим двоичным файлом, аргумент env
, переданный в execve
, создается из списка переменных динамически (с помощью listvars(VEXPORT, VUNSET, 0)
, вызываемого макросом environment()
).