Você sempre pode dizer ao seu shell para dizer aos aplicativos que código de shell leva à sua execução. Por exemplo, com zsh, passando essas informações na $SHELL_CODEvariável de ambiente usando o preexec()gancho ( printenvusado como exemplo, você usaria getenv("SHELL_CODE")em seu programa):
$ preexec() export SHELL_CODE=$1
$ printenv SHELL_CODE
printenv SHELL_CODE
$ printenv SHELL_CODE
printenv CODE
$ $(echo printenv SHELL_CODE)
$(echo printenv SHELL_CODE)
$ for i in SHELL_CODE; do printenv "$i"; done
for i in SHELL_CODE; do printenv "$i"; done
$ printenv SHELL_CODE; : other command
printenv SHELL_CODE; : other command
$ f() printenv SHELL_CODE
$ f
f
Todos aqueles seriam executados printenvcomo:
execve("/usr/bin/printenv", ["printenv", "SHELL_CODE"],
["PATH=...", ..., "SHELL_CODE=..."]);
Permitindo printenvrecuperar o código zsh que leva à execução printenvcom esses argumentos. O que você gostaria de fazer com essas informações não está claro para mim.
Com bash, o recurso mais próximo zsh's preexec()estaria usando seu $BASH_COMMANDem uma DEBUGarmadilha, mas nota que bashfaz algum nível de reescrever em que (e em refatora particulares alguns dos espaços em branco usado como delimitador) e que é aplicado a cada (bem, alguns) de comando executar, não toda a linha de comando, conforme inserido no prompt (consulte também a functraceopção).
$ trap 'export SHELL_CODE="$BASH_COMMAND"' DEBUG
$ printenv SHELL_CODE
printenv SHELL_CODE
$ printenv $(echo 'SHELL_CODE')
printenv $(echo 'SHELL_CODE')
$ for i in SHELL_CODE; do printenv "$i"; done; : other command
printenv "$i"
$ printf '%s\n' "$(printenv "SHELL_CODE")"
printf '%s\n' "$(printenv "SHELL_CODE")"
$ set -o functrace
$ printf '%s\n' "$(printenv "SHELL_CODE")"
printenv "SHELL_CODE"
$ print${-+env } $(echo 'SHELL_CODE')
print${-+env } $(echo 'SHELL_CODE')
Veja como alguns dos espaços delimitadores na sintaxe da linguagem shell foram compactados em 1 e como nem toda a linha de comando nem sempre é passada para o comando. Então provavelmente não é útil no seu caso.
Observe que eu não recomendaria esse tipo de coisa, pois você está potencialmente vazando informações confidenciais para todos os comandos, como em:
echo very_secret | wc -c | untrustedcmd
vazaria esse segredo para ambos wce untrustedcmd.
Claro, você poderia fazer esse tipo de coisa para outros idiomas além do shell. Por exemplo, em C, você pode usar algumas macros que exportam o código C que executa um comando para o ambiente:
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#define WRAP(x) (setenv("C_CODE", #x, 1), x)
int main(int argc, char *argv[])
{
if (!fork()) WRAP(execlp("printenv", "printenv", "C_CODE", NULL));
wait(NULL);
if (!fork()) WRAP(0 + execlp("printenv", "printenv", "C_CODE", NULL));
wait(NULL);
if (argc > 1 && !fork()) WRAP(execvp(argv[1], &argv[1]));
wait(NULL);
return 0;
}
Exemplo:
$ ./a.out printenv C_CODE
execlp("printenv", "printenv", "C_CODE", NULL)
0 + execlp("printenv", "printenv", "C_CODE", NULL)
execvp(argv[1], &argv[1])
Veja como alguns espaços foram condensados pelo pré-processador C, como no caso do bash. Na maioria dos idiomas, se não em todos os idiomas, a quantidade de espaço usada nos delimitadores não faz diferença; portanto, não é de surpreender que o compilador / intérprete tenha alguma liberdade com eles aqui.