Wird beim Übergeben von Argumenten an main()
eine C- oder C ++ - Anwendung argv[0]
immer der Name der ausführbaren Datei angegeben? Oder ist dies nur eine übliche Konvention und nicht garantiert, dass sie 100% der Zeit wahr ist?
102
execl("/home/hacker/.hidden/malicious", "/bin/ls", "-s", (char *)0);
. Der Name der ausführbaren Datei steht in keinem Zusammenhang mit dem Wert inargv[0]
.Antworten:
Vermutungen (sogar fundierte Vermutungen) machen Spaß, aber Sie müssen unbedingt zu den Standarddokumenten gehen, um sicherzugehen. Zum Beispiel heißt es in ISO C11 (mein Schwerpunkt):
Also nein, es ist nur der Programmname, wenn dieser Name verfügbar ist. Und es „steht für “ die Programmnamen, die nicht unbedingt ist der Programmname. Der vorhergehende Abschnitt besagt:
Dies ist unverändert gegenüber C99, dem vorherigen Standard, und bedeutet, dass selbst die Werte nicht vom Standard vorgegeben werden - es liegt ganz bei der Implementierung.
Dies bedeutet, dass der Programmname leer sein kann, wenn die Hostumgebung ihn nicht bereitstellt, und alles andere, wenn die Hostumgebung ihn bereitstellt, vorausgesetzt, dass "alles andere" irgendwie den Programmnamen darstellt. In meinen sadistischeren Momenten würde ich in Betracht ziehen, es ins Suaheli zu übersetzen, es durch eine Substitutions-Chiffre zu führen und es dann in umgekehrter Bytereihenfolge zu speichern :-).
Implementierungsdefiniert hat jedoch eine spezifische Bedeutung in den ISO-Standards - die Implementierung muss dokumentieren, wie sie funktioniert. Sogar UNIX, das
argv[0]
mit derexec
Familie der Aufrufe alles aufnehmen kann, was es will , muss (und tut) dies dokumentieren.quelle
argv[0]
ist für die Programmierung in der realen Welt von Vorteil.Unter
*nix
Typsysteme mitexec*()
Anrufenargv[0]
wird alles angezeigt, was der Anrufer an dieargv0
Stelle imexec*()
Anruf setzt.Die Shell verwendet die Konvention, dass dies der Programmname ist, und die meisten anderen Programme folgen derselben Konvention, daher
argv[0]
normalerweise der Programmname.Aber ein betrügerisches Unix-Programm kann alles aufrufen
exec()
und erstellen,argv[0]
was es möchte. Unabhängig davon, was der C-Standard sagt, können Sie sich nicht zu 100% darauf verlassen.quelle
Gemäß dem C ++ Standard, Abschnitt 3.6.1:
Also nein, es ist zumindest durch den Standard nicht garantiert.
quelle
In ISO-IEC 9899 heißt es:
Ich habe auch verwendet:
Und dann müssen Sie nur noch die Zeichenfolge analysieren, um den Namen der ausführbaren Datei aus dem Pfad zu extrahieren.
quelle
/proc/self/path/a.out
Symlink kann unter Solaris 10 und höher verwendet werden.GetModuleFileNameW
sollte verwendet werden, um einen beliebigen Pfad abrufen zu können, aber nur das Vorhandensein des Codes ist eine gute Anleitung).Diese Seite besagt:
Andere Seiten scheinen jedoch die Tatsache zu belegen, dass es sich immer um den Namen der ausführbaren Datei handelt. Dieser besagt:
quelle
argv[0]="-/bin/sh"
? Das ist jedenfalls bei allen Maschinen der Fall, die ich benutzt habe.Anwendungen mit
argv[0] !=
ausführbarem NamenViele Shells bestimmen durch Überprüfen, ob es sich um eine Login-Shell handelt
argv[0][0] == '-'
. Login-Shells haben unterschiedliche Eigenschaften, insbesondere, dass sie einige Standarddateien wie z/etc/profile
.Es ist in der Regel der Init selbst oder
getty
der führende-
, siehe auch: /unix/299408/how-to-login-automatically-without-typing-the-root-username-or-password -in-build / 300152 # 300152Binärdateien mit mehreren Anrufen, vielleicht vor allem Busybox . Diese verknüpfen mehrere Namen, z. B.
/bin/sh
und/bin/ls
mit einer einzelnen Exebutable/bin/busybox
, die erkennt, von welchem Tool aus sie verwendet werden sollenargv[0]
.Dies ermöglicht es, eine einzige kleine statisch verknüpfte ausführbare Datei zu haben, die mehrere Tools darstellt und grundsätzlich in jeder Linux-Umgebung funktioniert.
Siehe auch: /unix/315812/why-does-argv-include-the-program-name/315817
Ausführbares POSIX-
execve
Beispiel mitargv[0] !=
ausführbarem NamenAndere erwähnten
exec
, aber hier ist ein lauffähiges Beispiel.ac
bc
Dann:
Gibt:
Ja,
argv[0]
könnte auch sein:Getestet unter Ubuntu 16.10.
quelle
Ich bin mir nicht sicher, ob es sich um eine nahezu universelle Konvention oder einen Standard handelt, aber so oder so sollten Sie sich daran halten. Ich habe es jedoch noch nie außerhalb von Unix- und Unix-ähnlichen Systemen ausgenutzt gesehen. In Unix-Umgebungen - und möglicherweise besonders in früheren Zeiten - können Programme je nach dem Namen, unter dem sie aufgerufen werden, erheblich unterschiedliche Verhaltensweisen aufweisen.
BEARBEITET: Ich sehe aus anderen Posts zur gleichen Zeit wie ich, dass jemand festgestellt hat, dass es von einem bestimmten Standard stammt, aber ich bin sicher, dass die Konvention lange vor dem Standard liegt.
quelle
Wenn Sie ein Amiga-Programm mit Workbench starten, wird argv [0] nicht festgelegt, sondern nur mit CLI.
quelle