Anda selalu dapat memberi tahu shell Anda untuk memberi tahu aplikasi apa yang menyebabkan kode shell dijalankan. Misalnya, dengan zsh, dengan meneruskan informasi itu dalam $SHELL_CODEvariabel lingkungan menggunakan preexec()hook ( printenvdigunakan sebagai contoh, Anda akan menggunakannya getenv("SHELL_CODE")dalam program Anda):
$ 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
Semua itu akan dieksekusi printenvsebagai:
execve("/usr/bin/printenv", ["printenv", "SHELL_CODE"],
["PATH=...", ..., "SHELL_CODE=..."]);
Mengizinkan printenvuntuk mengambil kode zsh yang mengarah ke eksekusi printenvdengan argumen tersebut. Apa yang ingin Anda lakukan dengan informasi itu tidak jelas bagi saya.
Dengan bash, fitur yang paling dekat dengan zsh's preexec()akan menggunakan nya $BASH_COMMANDdalam DEBUGperangkap, tetapi catatan bahwa bashmelakukan beberapa tingkat menulis ulang dalam (dan di refactors khususnya beberapa spasi digunakan sebagai pembatas) dan bahwa ini diterapkan pada setiap (baik, beberapa) perintah jalankan, bukan seluruh baris perintah seperti yang dimasukkan pada prompt (lihat juga functraceopsi).
$ 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')
Lihat bagaimana beberapa spasi yang merupakan pembatas dalam sintaksis bahasa shell telah diperas menjadi 1 dan bagaimana tidak, baris perintah penuh tidak selalu diteruskan ke perintah. Jadi mungkin tidak berguna dalam kasus Anda.
Perhatikan bahwa saya tidak akan menyarankan melakukan hal semacam ini, karena Anda berpotensi membocorkan informasi sensitif ke setiap perintah seperti pada:
echo very_secret | wc -c | untrustedcmd
akan membocorkan rahasia itu untuk keduanya wcdan untrustedcmd.
Tentu saja, Anda bisa melakukan hal semacam itu untuk bahasa lain selain shell. Misalnya, dalam C, Anda bisa menggunakan beberapa makro yang mengekspor kode C yang mengeksekusi perintah ke lingkungan:
#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;
}
Contoh:
$ ./a.out printenv C_CODE
execlp("printenv", "printenv", "C_CODE", NULL)
0 + execlp("printenv", "printenv", "C_CODE", NULL)
execvp(argv[1], &argv[1])
Lihat bagaimana beberapa ruang dikondensasi oleh prosesor pra-C seperti dalam kasus bash. Dalam sebagian besar, jika tidak semua bahasa, jumlah ruang yang digunakan dalam pembatas tidak membuat perbedaan, jadi tidak mengherankan bahwa kompiler / penerjemah mengambil kebebasan di sini.