Sie können Ihrer Shell jederzeit mitteilen, welcher Shell-Code zu ihrer Ausführung geführt hat. Zum Beispiel mit zsh
, indem Sie diese Informationen in der $SHELL_CODE
Umgebungsvariablen mit dem preexec()
Hook übergeben ( printenv
als Beispiel, würden Sie getenv("SHELL_CODE")
in Ihrem Programm verwenden):
$ 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
Alle diese würden ausführen printenv
als:
execve("/usr/bin/printenv", ["printenv", "SHELL_CODE"],
["PATH=...", ..., "SHELL_CODE=..."]);
Ermöglicht printenv
das Abrufen des zsh-Codes, der zur Ausführung printenv
dieser Argumente führt. Was Sie mit diesen Informationen anfangen möchten, ist mir nicht klar.
Mit bash
dem Merkmal am nächsten zsh
ist preexec()
mit seiner würden $BASH_COMMAND
in einer DEBUG
Falle, aber beachten Sie, dass ein bash
gewisses Maß tut der in das Umschreiben (und insbesondere refactors einige der Leerzeichen als Trennzeichen verwendet wird ) , und das ist auf jeden angewandt (na ja, etwas) Befehl Führen Sie nicht die gesamte Befehlszeile aus, wie an der Eingabeaufforderung angegeben (siehe auch die functrace
Option).
$ 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')
Sehen Sie, wie einige der Leerzeichen, die Trennzeichen in der Shell-Sprachensyntax sind, in 1 gequetscht wurden und wie nicht immer die vollständige Befehlszeile an den Befehl übergeben wird. Also in deinem Fall wohl nicht sinnvoll.
Beachten Sie, dass ich Ihnen davon abraten würde, da Sie potenziell vertrauliche Informationen an jeden Befehl weitergeben, wie in:
echo very_secret | wc -c | untrustedcmd
würde dieses Geheimnis an beide wc
und weitergeben untrustedcmd
.
Natürlich können Sie so etwas auch für andere Sprachen als die Shell tun. In C könnten Sie beispielsweise einige Makros verwenden, die den C-Code, der einen Befehl ausführt, in die Umgebung exportieren:
#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;
}
Beispiel:
$ ./a.out printenv C_CODE
execlp("printenv", "printenv", "C_CODE", NULL)
0 + execlp("printenv", "printenv", "C_CODE", NULL)
execvp(argv[1], &argv[1])
Sehen Sie, wie einige Leerzeichen vom C-Preprozessor komprimiert wurden, wie im Bash-Fall. In den meisten, wenn nicht allen Sprachen, spielt der in Begrenzungszeichen verwendete Speicherplatz keine Rolle. Daher ist es nicht verwunderlich, dass der Compiler / Interpreter hier etwas Freiheit mit sich nimmt.