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_CODE
variabel lingkungan menggunakan preexec()
hook ( printenv
digunakan 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 printenv
sebagai:
execve("/usr/bin/printenv", ["printenv", "SHELL_CODE"],
["PATH=...", ..., "SHELL_CODE=..."]);
Mengizinkan printenv
untuk mengambil kode zsh yang mengarah ke eksekusi printenv
dengan 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_COMMAND
dalam DEBUG
perangkap, tetapi catatan bahwa bash
melakukan 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 functrace
opsi).
$ 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 wc
dan 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.