landley / toybox

toybox
http://landley.net/toybox
BSD Zero Clause License
2.44k stars 340 forks source link

[FR] envsubst #507

Open gfrankliu opened 5 months ago

gfrankliu commented 5 months ago

envsubst is frequently used in container world for environment variable substitution. It was added in Alpine as discussed in https://gitlab.alpinelinux.org/alpine/aports/-/issues/14935 Does it make sense to include it as a toybox command?

landley commented 5 months ago

It might? Neither the man page nor the --help output explain what it does (what's shell-format). envsubst -v PATH didn't print anything, and envsubst -v '$PATH' printed PATH...

So it's basically you want something like:

$ echo '$SHLVL/$DISPLAY' | eval $'cat << EOF\n'"$(cat)"$'\nEOF\n' 1/:0.0

Except as a standalone shell command? I mean, I suppose I could do it as a shell builtin instead of a shell function. Not entirely sure WHY, but... sure?

Have you tried asking Chet the bash maintainer if he thinks there's already a way to do this built in to bash? Seems like there should be somewhere, a trivial shell function with some sort of ${1@Q} or declare corner case...

landley commented 5 months ago

And you want a safe command that's not gonna $(subshell) and so on.

Writing it seems trivial, especially if I can leverage the code I already wrote for toysh. Working out what the specification actually IS, not so much.

gfrankliu commented 5 months ago

Here is the man page: https://man7.org/linux/man-pages/man1/envsubst.1.html and some examples https://www.baeldung.com/linux/envsubst-command

It is a utility by itself, not a shell builtin.

eg: https://pkgs.alpinelinux.org/package/edge/testing/x86_64/envsubst https://github.com/a8m/envsubst

landley commented 5 months ago

That would be the man page I mentioned not finding particularly enlightening, yes. The examples are helpful though, thanks. (I never would have guessed that shell-format was INSANE enough to need the $ on the variable name to be substituted.)

I'm aware it's a standalone command, most external packages are, I'm just saying it would be easier for me to implement it as a shell builtin because the shell already has variable resolution plumbing including the various ${name/search/replace} that https://github.com/kaniini/envsubst/issues/1 has an open issue for (I'd more or less get that for free).

However, they presumably want it NOT to run $(subshell) and so on for security reasons, which doesn't sound hard to block but I'd want to think about the design a bit to be sure.

As for having a shell builtin that's also available as a standalone command in the $PATH... well that's kind of what TOYFLAG_MAYFORK does, except sort of in reverse here. (The tricksy part is that scripts/single.sh special cases sh for standalone builds and I'd need to categorize this properly. This command wants to use the shell plumbing, but without the shell builtin variables like $OLDPWD and $RANDOM because echo '$RANDOM' | env -i envsubst doesn't print them. Possibly some chunk of code should get factored out...)