Uygulamaya, kabuk kodunun yürütülmesine hangi kabuk kodun yol açtığını söylemesini her zaman söyleyebilirsiniz. Örneğin, zsh
bu bilgileri kancayı $SHELL_CODE
kullanarak ortam değişkenine geçirerek preexec()
( printenv
örnek olarak kullanılır getenv("SHELL_CODE")
, programınızda kullanırsınız):
$ 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
Bütün printenv
bunlar şu şekilde yürütülür :
execve("/usr/bin/printenv", ["printenv", "SHELL_CODE"],
["PATH=...", ..., "SHELL_CODE=..."]);
Bu argümanlarla printenv
yürütülmesine yol açan zsh kodunun alınmasına izin verilmesi printenv
. Bu bilgi ile ne yapmak istediğinizi bana açık değildir.
İle bash
özelliğiyle en yakın, zsh
s' preexec()
onun kullanarak olacağını $BASH_COMMAND
bir de DEBUG
tuzak, ancak not bash
(iyi bazı) (özellikle refactors de ayırıcı olarak kullanılan boşluk bazı ve) ve bu en her uygulanmış ki yeniden belli bir düzeyde yapar komut komut satırında girilen komut satırının tamamını değil (aynı zamanda functrace
seçeneğe bakın).
$ 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')
Kabuk dili sözdiziminde sınırlayıcı olan boşlukların bazılarının 1'e nasıl sıkıştırıldığını ve tam komut satırının her zaman komuta alınmadığını görün. Muhtemelen davanda işe yaramaz.
Her türlü komutta aşağıdaki gibi hassas bilgileri potansiyel olarak sızdırıyorsanız, bu tür bir işlem yapmamayacağımı unutmayın:
echo very_secret | wc -c | untrustedcmd
hem bu sırrı kaçırır ama wc
ve untrustedcmd
.
Tabii ki, bu tür bir şeyi kabuktan başka diller için de yapabilirsin. Örneğin, C’de, bir komutu çalıştıran C kodunu çevreye veren bazı makroları kullanabilirsiniz:
#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;
}
Örnek:
$ ./a.out printenv C_CODE
execlp("printenv", "printenv", "C_CODE", NULL)
0 + execlp("printenv", "printenv", "C_CODE", NULL)
execvp(argv[1], &argv[1])
Bazı durumlarda, bash durumundaki gibi C ön işlemcisi tarafından nasıl yoğunlaştırıldığını görün. Çoğunlukla tüm diller değilse, sınırlayıcılarda kullanılan alan miktarı bir fark yaratmaz, bu nedenle derleyicinin / tercümanın burada onlarla biraz özgürlük kazanması şaşırtıcı değildir.