Die Verwendung von /proc/self/exe
ist nicht tragbar und unzuverlässig. Auf meinem Ubuntu 12.04-System müssen Sie root sein, um den Symlink lesen / folgen zu können. Dies führt dazu, dass das Boost-Beispiel und wahrscheinlich die veröffentlichten whereami()
Lösungen fehlschlagen.
Dieser Beitrag ist sehr lang, behandelt jedoch die tatsächlichen Probleme und präsentiert Code, der zusammen mit der Validierung anhand einer Testsuite funktioniert.
Der beste Weg, um Ihr Programm zu finden, besteht darin, die gleichen Schritte zurückzuverfolgen, die das System verwendet. Dies erfolgt durch die Verwendung von argv[0]
aufgelöst gegen Dateisystemstamm, pwd, Pfadumgebung und unter Berücksichtigung von Symlinks und der Kanonisierung von Pfadnamen. Dies ist aus dem Gedächtnis, aber ich habe dies in der Vergangenheit erfolgreich gemacht und es in einer Vielzahl von verschiedenen Situationen getestet. Es ist nicht garantiert, dass es funktioniert, aber wenn dies nicht der Fall ist, haben Sie wahrscheinlich viel größere Probleme und es ist insgesamt zuverlässiger als alle anderen besprochenen Methoden. Es gibt Situationen auf einem Unix-kompatiblen System, in denen eine ordnungsgemäße Handhabung erfolgtargv[0]
Sie gelangen nicht zu Ihrem Programm, aber dann werden Sie in einer nachweislich fehlerhaften Umgebung ausgeführt. Es ist auch ziemlich portabel für alle von Unix abgeleiteten Systeme seit etwa 1970 und sogar für einige nicht von Unix abgeleitete Systeme, da es im Wesentlichen auf der Standardfunktionalität von libc () und der Standardbefehlszeilenfunktionalität basiert. Es sollte unter Linux (alle Versionen), Android, Chrome OS, Minix, Original Bell Labs Unix, FreeBSD, NetBSD, OpenBSD, BSD xx, SunOS, Solaris, SYSV, HPUX, Concentrix, SCO, Darwin, AIX, OS X, funktionieren. Nächster Schritt usw. Und mit einer kleinen Änderung wahrscheinlich VMS, VM / CMS, DOS / Windows, ReactOS, OS / 2 usw. Wenn ein Programm direkt von einer GUI-Umgebung aus gestartet wurde, sollte es argv[0]
einen absoluten Pfad festgelegt haben.
Verstehen Sie, dass fast jede Shell auf jedem Unix-kompatiblen Betriebssystem, das jemals veröffentlicht wurde, Programme grundsätzlich auf dieselbe Weise findet und die Betriebsumgebung fast auf dieselbe Weise einrichtet (mit einigen optionalen Extras). Von jedem anderen Programm, das ein Programm startet, wird erwartet, dass es für dieses Programm dieselbe Umgebung (argv, Umgebungszeichenfolgen usw.) erstellt, als würde es von einer Shell ausgeführt, mit einigen optionalen Extras. Ein Programm oder Benutzer kann eine von dieser Konvention abweichende Umgebung für andere untergeordnete Programme einrichten, die es startet. Wenn dies jedoch der Fall ist, handelt es sich um einen Fehler, und das Programm hat keine vernünftige Erwartung, dass das untergeordnete Programm oder seine Untergebenen ordnungsgemäß funktionieren.
Mögliche Werte von argv[0]
include:
/path/to/executable
- absoluter Pfad
../bin/executable
- relativ zu pwd
bin/executable
- relativ zu pwd
./foo
- relativ zu pwd
executable
- Basisname, im Pfad finden
bin//executable
- relativ zu pwd, nicht kanonisch
src/../bin/executable
- relativ zu pwd, nicht kanonisch, backtracking
bin/./echoargc
- relativ zu pwd, nicht kanonisch
Werte, die Sie nicht sehen sollten:
~/bin/executable
- neu geschrieben, bevor Ihr Programm ausgeführt wird.
~user/bin/executable
- neu geschrieben, bevor Ihr Programm ausgeführt wird
alias
- neu geschrieben, bevor Ihr Programm ausgeführt wird
$shellvariable
- neu geschrieben, bevor Ihr Programm ausgeführt wird
*foo*
- Platzhalter, neu geschrieben, bevor Ihr Programm ausgeführt wird, nicht sehr nützlich
?foo?
- Platzhalter, neu geschrieben, bevor Ihr Programm ausgeführt wird, nicht sehr nützlich
Darüber hinaus können diese nicht-kanonische Pfadnamen und mehrere Ebenen symbolischer Verknüpfungen enthalten. In einigen Fällen kann es mehrere feste Links zu demselben Programm geben. Zum Beispiel /bin/ls
, /bin/ps
, /bin/chmod
, /bin/rm
kann etc. harte Links sein /bin/busybox
.
Führen Sie die folgenden Schritte aus, um sich selbst zu finden:
Speichern Sie pwd, PATH und argv [0] beim Eintritt in Ihr Programm (oder bei der Initialisierung Ihrer Bibliothek), da sie sich später ändern können.
Optional: Insbesondere bei Nicht-Unix-Systemen sollten Sie den Pfadnamen Host / Benutzer / Laufwerk-Präfix-Teil, falls vorhanden, trennen, aber nicht verwerfen. der Teil, der häufig vor einem Doppelpunkt steht oder einem anfänglichen "//" folgt.
Wenn argv[0]
es sich um einen absoluten Pfad handelt, verwenden Sie diesen als Ausgangspunkt. Ein absoluter Pfad beginnt wahrscheinlich mit "/", aber auf einigen Nicht-Unix-Systemen beginnt er möglicherweise mit "\" oder einem Laufwerksbuchstaben oder einem Namenspräfix, gefolgt von einem Doppelpunkt.
Andernfalls, wenn argv[0]
es sich um einen relativen Pfad handelt (enthält "/" oder "\", beginnt aber nicht damit, z. B. "../../bin/foo", kombinieren Sie pwd + "/" + argv [0] (verwenden Sie) vorhandenes Arbeitsverzeichnis ab dem Zeitpunkt des Programmstarts, nicht aktuell).
Andernfalls, wenn argv [0] ein einfacher Basisname ist (keine Schrägstriche), kombinieren Sie ihn nacheinander mit jedem Eintrag in der Umgebungsvariablen PATH und probieren Sie diese aus und verwenden Sie den ersten, der erfolgreich ist.
Optional: Else versucht , den sehr plattformspezifisch /proc/self/exe
, /proc/curproc/file
(BSD), und (char *)getauxval(AT_EXECFN)
, und , dlgetname(...)
falls vorhanden. Sie können diese zuvor argv[0]
basierten Methoden sogar ausprobieren , wenn sie verfügbar sind und keine Berechtigungsprobleme auftreten. In dem eher unwahrscheinlichen Fall (wenn Sie alle Versionen aller Systeme berücksichtigen), dass sie vorhanden sind und nicht ausfallen, sind sie möglicherweise maßgeblicher.
Optional: Überprüfen Sie mithilfe eines Befehlszeilenparameters, ob ein Pfadname übergeben wurde.
Optional: Suchen Sie in der Umgebung nach einem Pfadnamen, der von Ihrem Wrapper-Skript explizit übergeben wurde, falls vorhanden.
Optional: Versuchen Sie als letzten Ausweg die Umgebungsvariable "_". Es könnte auf ein völlig anderes Programm verweisen, beispielsweise auf die Benutzer-Shell.
Lösen Sie Symlinks auf, es können mehrere Ebenen vorhanden sein. Es besteht die Möglichkeit von Endlosschleifen. Wenn diese vorhanden sind, wird Ihr Programm wahrscheinlich nicht aufgerufen.
Kanonisieren Sie den Dateinamen, indem Sie Teilzeichenfolgen wie "/foo/../bar/" in "/ bar /" auflösen. Beachten Sie, dass dies möglicherweise die Bedeutung ändert, wenn Sie einen Netzwerk-Mount-Punkt überschreiten. Daher ist die Kanonisierung nicht immer eine gute Sache. Auf einem Netzwerkserver kann ".." in symlink verwendet werden, um einen Pfad zu einer anderen Datei im Serverkontext anstatt auf dem Client zu durchlaufen. In diesem Fall möchten Sie wahrscheinlich den Client-Kontext, sodass die Kanonisierung in Ordnung ist. Konvertieren Sie auch Muster wie "/./" in "/" und "//" in "/". readlink --canonicalize
Löst in der Shell mehrere Symlinks auf und kanonisiert den Namen. Chase kann ähnlich vorgehen, ist aber nicht installiert. realpath()
oder canonicalize_file_name()
, falls vorhanden, kann helfen.
Wenn realpath()
dies zur Kompilierungszeit nicht vorhanden ist, können Sie eine Kopie von einer zulässigen lizenzierten Bibliotheksdistribution ausleihen und in sich selbst kompilieren, anstatt das Rad neu zu erfinden. Korrigieren Sie den möglichen Pufferüberlauf (übergeben Sie die Größe des Ausgabepuffers, denken Sie an strncpy () vs strcpy ()), wenn Sie einen Puffer verwenden, der kleiner als PATH_MAX ist. Es ist möglicherweise einfacher, nur eine umbenannte private Kopie zu verwenden, als zu testen, ob sie vorhanden ist. Zulässige Lizenzkopie von android / darwin / bsd:
https://android.googlesource.com/platform/bionic/+/f077784/libc/upstream-freebsd/lib/libc/stdlib/realpath.c
Beachten Sie, dass mehrere Versuche erfolgreich oder teilweise erfolgreich sein können und möglicherweise nicht alle auf dieselbe ausführbare Datei verweisen. Überprüfen Sie daher Ihre ausführbare Datei. Möglicherweise haben Sie jedoch keine Leseberechtigung. Wenn Sie diese nicht lesen können, behandeln Sie dies nicht als Fehler. Oder überprüfen Sie etwas in der Nähe Ihrer ausführbaren Datei, z. B. das Verzeichnis "../lib/", das Sie suchen. Möglicherweise verfügen Sie über mehrere Versionen, gepackte und lokal kompilierte Versionen, lokale und Netzwerkversionen sowie tragbare Versionen mit lokalem und USB-Laufwerk usw., und es besteht eine geringe Wahrscheinlichkeit, dass Sie zwei inkompatible Ergebnisse mit unterschiedlichen Suchmethoden erhalten. Und "_" kann einfach auf das falsche Programm verweisen.
Ein Programm, das verwendet, execve
kann absichtlich so eingestellt werden argv[0]
, dass es nicht mit dem tatsächlichen Pfad kompatibel ist, der zum Laden des Programms verwendet wird, und PATH, "_", pwd usw. beschädigt, obwohl es im Allgemeinen nicht viele Gründe dafür gibt. Dies kann jedoch Auswirkungen auf die Sicherheit haben, wenn Sie anfälligen Code haben, der die Tatsache ignoriert, dass Ihre Ausführungsumgebung auf verschiedene Arten geändert werden kann, einschließlich, aber nicht beschränkt auf diese (Chroot, Fuse-Dateisystem, Hardlinks usw.). Dies ist möglich Damit Shell-Befehle PATH festlegen, aber nicht exportieren können.
Sie müssen nicht unbedingt für Nicht-Unix-Systeme codieren, aber es wäre eine gute Idee, sich einiger Besonderheiten bewusst zu sein, damit Sie den Code so schreiben können, dass es für jemanden nicht so schwierig ist, ihn später zu portieren . Beachten Sie, dass einige Systeme (DEC VMS, DOS, URLs usw.) möglicherweise Laufwerksnamen oder andere Präfixe haben, die mit einem Doppelpunkt wie "C: \", "sys $ drive: [foo] bar" und "file" enden : /// foo / bar / baz ". Alte DEC VMS-Systeme verwenden "[" und "]", um den Verzeichnisabschnitt des Pfads einzuschließen, obwohl sich dies möglicherweise geändert hat, wenn Ihr Programm in einer POSIX-Umgebung kompiliert wurde. Einige Systeme, wie z. B. VMS, haben möglicherweise eine Dateiversion (am Ende durch ein Semikolon getrennt). Einige Systeme verwenden zwei aufeinanderfolgende Schrägstriche wie "// Laufwerk / Pfad / zu / Datei" oder "Benutzer @ Host: / Pfad / zu / Datei" (Befehl scp) oder "Datei: (durch Leerzeichen getrennt) und "PATH" durch Doppelpunkte getrennt, aber Ihr Programm sollte PATH erhalten, damit Sie sich keine Gedanken über den Pfad machen müssen. DOS und einige andere Systeme können relative Pfade haben, die mit einem Laufwerkpräfix beginnen. C: foo.exe bezieht sich auf foo.exe im aktuellen Verzeichnis auf Laufwerk C, daher müssen Sie das aktuelle Verzeichnis auf C: suchen und dieses für pwd verwenden. (durch Leerzeichen getrennt) und "PATH" durch Doppelpunkte getrennt, aber Ihr Programm sollte PATH erhalten, damit Sie sich keine Gedanken über den Pfad machen müssen. DOS und einige andere Systeme können relative Pfade haben, die mit einem Laufwerkpräfix beginnen. C: foo.exe bezieht sich auf foo.exe im aktuellen Verzeichnis auf Laufwerk C, daher müssen Sie das aktuelle Verzeichnis auf C: suchen und dieses für pwd verwenden.
Ein Beispiel für Symlinks und Wrapper auf meinem System:
/usr/bin/google-chrome is symlink to
/etc/alternatives/google-chrome which is symlink to
/usr/bin/google-chrome-stable which is symlink to
/opt/google/chrome/google-chrome which is a bash script which runs
/opt/google/chome/chrome
Beachten Sie, dass Benutzer Rechnung geschrieben einen Link oben auf ein Programm bei HP, die die drei Grundfälle behandelt argv[0]
. Es bedarf jedoch einiger Änderungen:
- Es wird notwendig sein, alle neu zu schreiben
strcat()
und strcpy()
zu verwenden strncat()
und strncpy()
. Obwohl die Variablen mit der Länge PATHMAX deklariert sind, ist ein Eingabewert der Länge PATHMAX-1 plus der Länge der verketteten Zeichenfolgen> PATHMAX, und ein Eingabewert der Länge PATHMAX wäre nicht abgeschlossen.
- Es muss als Bibliotheksfunktion neu geschrieben werden und nicht nur zum Ausdrucken der Ergebnisse.
- Namen können nicht kanonisiert werden (verwenden Sie den oben verlinkten Realpath-Code)
- Symbolische Links können nicht aufgelöst werden (verwenden Sie den Realpath-Code).
Wenn Sie also sowohl den HP-Code als auch den Realpath-Code kombinieren und beide so korrigieren, dass sie gegen Pufferüberläufe resistent sind, sollten Sie etwas haben, das richtig interpretiert werden kann argv[0]
.
Im Folgenden werden die tatsächlichen Werte argv[0]
für verschiedene Möglichkeiten zum Aufrufen desselben Programms unter Ubuntu 12.04 dargestellt. Und ja, das Programm wurde versehentlich echoargc anstelle von echoargv genannt. Dies wurde mit einem Skript zum sauberen Kopieren durchgeführt, aber das manuelle Ausführen in der Shell führt zu denselben Ergebnissen (außer, dass Aliase im Skript nur funktionieren, wenn Sie sie explizit aktivieren).
cat ~/src/echoargc.c
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
main(int argc, char **argv)
{
printf(" argv[0]=\"%s\"\n", argv[0]);
sleep(1); /* in case run from desktop */
}
tcc -o ~/bin/echoargc ~/src/echoargc.c
cd ~
/home/whitis/bin/echoargc
argv[0]="/home/whitis/bin/echoargc"
echoargc
argv[0]="echoargc"
bin/echoargc
argv[0]="bin/echoargc"
bin//echoargc
argv[0]="bin//echoargc"
bin/./echoargc
argv[0]="bin/./echoargc"
src/../bin/echoargc
argv[0]="src/../bin/echoargc"
cd ~/bin
*echo*
argv[0]="echoargc"
e?hoargc
argv[0]="echoargc"
./echoargc
argv[0]="./echoargc"
cd ~/src
../bin/echoargc
argv[0]="../bin/echoargc"
cd ~/junk
~/bin/echoargc
argv[0]="/home/whitis/bin/echoargc"
~whitis/bin/echoargc
argv[0]="/home/whitis/bin/echoargc"
alias echoit=~/bin/echoargc
echoit
argv[0]="/home/whitis/bin/echoargc"
echoarg=~/bin/echoargc
$echoarg
argv[0]="/home/whitis/bin/echoargc"
ln -s ~/bin/echoargc junk1
./junk1
argv[0]="./junk1"
ln -s /home/whitis/bin/echoargc junk2
./junk2
argv[0]="./junk2"
ln -s junk1 junk3
./junk3
argv[0]="./junk3"
gnome-desktop-item-edit --create-new ~/Desktop
# interactive, create desktop link, then click on it
argv[0]="/home/whitis/bin/echoargc"
# interactive, right click on gnome application menu, pick edit menus
# add menu item for echoargc, then run it from gnome menu
argv[0]="/home/whitis/bin/echoargc"
cat ./testargcscript 2>&1 | sed -e 's/^/ /g'
#!/bin/bash
# echoargc is in ~/bin/echoargc
# bin is in path
shopt -s expand_aliases
set -v
cat ~/src/echoargc.c
tcc -o ~/bin/echoargc ~/src/echoargc.c
cd ~
/home/whitis/bin/echoargc
echoargc
bin/echoargc
bin//echoargc
bin/./echoargc
src/../bin/echoargc
cd ~/bin
*echo*
e?hoargc
./echoargc
cd ~/src
../bin/echoargc
cd ~/junk
~/bin/echoargc
~whitis/bin/echoargc
alias echoit=~/bin/echoargc
echoit
echoarg=~/bin/echoargc
$echoarg
ln -s ~/bin/echoargc junk1
./junk1
ln -s /home/whitis/bin/echoargc junk2
./junk2
ln -s junk1 junk3
./junk3
Diese Beispiele veranschaulichen, dass die in diesem Beitrag beschriebenen Techniken unter einer Vielzahl von Umständen funktionieren sollten und warum einige der Schritte erforderlich sind.
BEARBEITEN: Jetzt wurde das Programm, das argv [0] druckt, aktualisiert, um sich selbst zu finden.
// Copyright 2015 by Mark Whitis. License=MIT style
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <limits.h>
#include <assert.h>
#include <string.h>
#include <errno.h>
// "look deep into yourself, Clarice" -- Hanibal Lector
char findyourself_save_pwd[PATH_MAX];
char findyourself_save_argv0[PATH_MAX];
char findyourself_save_path[PATH_MAX];
char findyourself_path_separator='/';
char findyourself_path_separator_as_string[2]="/";
char findyourself_path_list_separator[8]=":"; // could be ":; "
char findyourself_debug=0;
int findyourself_initialized=0;
void findyourself_init(char *argv0)
{
getcwd(findyourself_save_pwd, sizeof(findyourself_save_pwd));
strncpy(findyourself_save_argv0, argv0, sizeof(findyourself_save_argv0));
findyourself_save_argv0[sizeof(findyourself_save_argv0)-1]=0;
strncpy(findyourself_save_path, getenv("PATH"), sizeof(findyourself_save_path));
findyourself_save_path[sizeof(findyourself_save_path)-1]=0;
findyourself_initialized=1;
}
int find_yourself(char *result, size_t size_of_result)
{
char newpath[PATH_MAX+256];
char newpath2[PATH_MAX+256];
assert(findyourself_initialized);
result[0]=0;
if(findyourself_save_argv0[0]==findyourself_path_separator) {
if(findyourself_debug) printf(" absolute path\n");
realpath(findyourself_save_argv0, newpath);
if(findyourself_debug) printf(" newpath=\"%s\"\n", newpath);
if(!access(newpath, F_OK)) {
strncpy(result, newpath, size_of_result);
result[size_of_result-1]=0;
return(0);
} else {
perror("access failed 1");
}
} else if( strchr(findyourself_save_argv0, findyourself_path_separator )) {
if(findyourself_debug) printf(" relative path to pwd\n");
strncpy(newpath2, findyourself_save_pwd, sizeof(newpath2));
newpath2[sizeof(newpath2)-1]=0;
strncat(newpath2, findyourself_path_separator_as_string, sizeof(newpath2));
newpath2[sizeof(newpath2)-1]=0;
strncat(newpath2, findyourself_save_argv0, sizeof(newpath2));
newpath2[sizeof(newpath2)-1]=0;
realpath(newpath2, newpath);
if(findyourself_debug) printf(" newpath=\"%s\"\n", newpath);
if(!access(newpath, F_OK)) {
strncpy(result, newpath, size_of_result);
result[size_of_result-1]=0;
return(0);
} else {
perror("access failed 2");
}
} else {
if(findyourself_debug) printf(" searching $PATH\n");
char *saveptr;
char *pathitem;
for(pathitem=strtok_r(findyourself_save_path, findyourself_path_list_separator, &saveptr); pathitem; pathitem=strtok_r(NULL, findyourself_path_list_separator, &saveptr) ) {
if(findyourself_debug>=2) printf("pathitem=\"%s\"\n", pathitem);
strncpy(newpath2, pathitem, sizeof(newpath2));
newpath2[sizeof(newpath2)-1]=0;
strncat(newpath2, findyourself_path_separator_as_string, sizeof(newpath2));
newpath2[sizeof(newpath2)-1]=0;
strncat(newpath2, findyourself_save_argv0, sizeof(newpath2));
newpath2[sizeof(newpath2)-1]=0;
realpath(newpath2, newpath);
if(findyourself_debug) printf(" newpath=\"%s\"\n", newpath);
if(!access(newpath, F_OK)) {
strncpy(result, newpath, size_of_result);
result[size_of_result-1]=0;
return(0);
}
} // end for
perror("access failed 3");
} // end else
// if we get here, we have tried all three methods on argv[0] and still haven't succeeded. Include fallback methods here.
return(1);
}
main(int argc, char **argv)
{
findyourself_init(argv[0]);
char newpath[PATH_MAX];
printf(" argv[0]=\"%s\"\n", argv[0]);
realpath(argv[0], newpath);
if(strcmp(argv[0],newpath)) { printf(" realpath=\"%s\"\n", newpath); }
find_yourself(newpath, sizeof(newpath));
if(1 || strcmp(argv[0],newpath)) { printf(" findyourself=\"%s\"\n", newpath); }
sleep(1); /* in case run from desktop */
}
Und hier ist die Ausgabe, die zeigt, dass sie sich in jedem der vorherigen Tests tatsächlich selbst gefunden hat.
tcc -o ~/bin/echoargc ~/src/echoargc.c
cd ~
/home/whitis/bin/echoargc
argv[0]="/home/whitis/bin/echoargc"
findyourself="/home/whitis/bin/echoargc"
echoargc
argv[0]="echoargc"
realpath="/home/whitis/echoargc"
findyourself="/home/whitis/bin/echoargc"
bin/echoargc
argv[0]="bin/echoargc"
realpath="/home/whitis/bin/echoargc"
findyourself="/home/whitis/bin/echoargc"
bin//echoargc
argv[0]="bin//echoargc"
realpath="/home/whitis/bin/echoargc"
findyourself="/home/whitis/bin/echoargc"
bin/./echoargc
argv[0]="bin/./echoargc"
realpath="/home/whitis/bin/echoargc"
findyourself="/home/whitis/bin/echoargc"
src/../bin/echoargc
argv[0]="src/../bin/echoargc"
realpath="/home/whitis/bin/echoargc"
findyourself="/home/whitis/bin/echoargc"
cd ~/bin
*echo*
argv[0]="echoargc"
realpath="/home/whitis/bin/echoargc"
findyourself="/home/whitis/bin/echoargc"
e?hoargc
argv[0]="echoargc"
realpath="/home/whitis/bin/echoargc"
findyourself="/home/whitis/bin/echoargc"
./echoargc
argv[0]="./echoargc"
realpath="/home/whitis/bin/echoargc"
findyourself="/home/whitis/bin/echoargc"
cd ~/src
../bin/echoargc
argv[0]="../bin/echoargc"
realpath="/home/whitis/bin/echoargc"
findyourself="/home/whitis/bin/echoargc"
cd ~/junk
~/bin/echoargc
argv[0]="/home/whitis/bin/echoargc"
findyourself="/home/whitis/bin/echoargc"
~whitis/bin/echoargc
argv[0]="/home/whitis/bin/echoargc"
findyourself="/home/whitis/bin/echoargc"
alias echoit=~/bin/echoargc
echoit
argv[0]="/home/whitis/bin/echoargc"
findyourself="/home/whitis/bin/echoargc"
echoarg=~/bin/echoargc
$echoarg
argv[0]="/home/whitis/bin/echoargc"
findyourself="/home/whitis/bin/echoargc"
rm junk1 junk2 junk3
ln -s ~/bin/echoargc junk1
./junk1
argv[0]="./junk1"
realpath="/home/whitis/bin/echoargc"
findyourself="/home/whitis/bin/echoargc"
ln -s /home/whitis/bin/echoargc junk2
./junk2
argv[0]="./junk2"
realpath="/home/whitis/bin/echoargc"
findyourself="/home/whitis/bin/echoargc"
ln -s junk1 junk3
./junk3
argv[0]="./junk3"
realpath="/home/whitis/bin/echoargc"
findyourself="/home/whitis/bin/echoargc"
Die beiden oben beschriebenen GUI-Starts finden das Programm ebenfalls korrekt.
Es gibt eine mögliche Gefahr. Die access()
Funktion löscht Berechtigungen, wenn das Programm vor dem Testen eingestellt wurde. Wenn es eine Situation gibt, in der das Programm als erhöhter Benutzer, aber nicht als normaler Benutzer gefunden werden kann, kann es vorkommen, dass diese Tests fehlschlagen, obwohl es unwahrscheinlich ist, dass das Programm unter diesen Umständen tatsächlich ausgeführt wird. Man könnte stattdessen euidaccess () verwenden. Es ist jedoch möglich, dass ein unzugängliches Programm früher auf dem Pfad gefunden wird als der tatsächliche Benutzer.