Bạn luôn có thể nói với shell của bạn để cho các ứng dụng biết mã shell nào dẫn đến việc thực thi chúng. Chẳng hạn, với zsh
, bằng cách chuyển thông tin đó trong $SHELL_CODE
biến môi trường bằng cách sử dụng preexec()
hook ( printenv
được sử dụng làm ví dụ, bạn sẽ sử dụng getenv("SHELL_CODE")
trong chương trình của mình):
$ 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
Tất cả những người sẽ thực hiện printenv
như:
execve("/usr/bin/printenv", ["printenv", "SHELL_CODE"],
["PATH=...", ..., "SHELL_CODE=..."]);
Cho phép printenv
truy xuất mã zsh dẫn đến việc thực thi printenv
với các đối số đó. Những gì bạn muốn làm với thông tin đó là không rõ ràng với tôi.
Với bash
, tính năng gần zsh
's preexec()
sẽ sử dụng nó $BASH_COMMAND
trong một DEBUG
cái bẫy, nhưng lưu ý rằng bash
hiện một số mức độ viết lại ở đó (và trong refactors đặc biệt một số các khoảng trắng dùng làm dấu phân cách) và của áp dụng cho mỗi (tốt, một số) lệnh chạy, không phải toàn bộ dòng lệnh như được nhập tại dấu nhắc (xem thêm functrace
tùy chọ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')
Xem làm thế nào một số khoảng trắng là dấu phân cách trong cú pháp ngôn ngữ shell đã được nén thành 1 và làm thế nào không phải dòng lệnh đầy đủ không luôn luôn được truyền cho lệnh. Vì vậy, có lẽ không hữu ích trong trường hợp của bạn.
Lưu ý rằng tôi sẽ không khuyên bạn thực hiện loại điều này, vì bạn có khả năng rò rỉ thông tin nhạy cảm cho mọi lệnh như trong:
echo very_secret | wc -c | untrustedcmd
sẽ rò rỉ bí mật đó cho cả hai wc
và untrustedcmd
.
Tất nhiên, bạn có thể làm điều đó cho các ngôn ngữ khác ngoài shell. Ví dụ: trong C, bạn có thể sử dụng một số macro xuất mã C thực thi lệnh ra môi trường:
#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;
}
Thí dụ:
$ ./a.out printenv C_CODE
execlp("printenv", "printenv", "C_CODE", NULL)
0 + execlp("printenv", "printenv", "C_CODE", NULL)
execvp(argv[1], &argv[1])
Xem cách một số khoảng trắng được bộ xử lý trước C ngưng tụ như trong trường hợp bash. Trong hầu hết nếu không phải tất cả các ngôn ngữ, lượng không gian được sử dụng trong các dấu phân cách không có sự khác biệt, vì vậy không có gì đáng ngạc nhiên khi trình biên dịch / trình thông dịch có một số quyền tự do với chúng ở đây.