Ve skutečnosti to není odpověď, ale pouze poznámka, kterou je třeba mít na paměti.
Jak jsme viděli, problém nalezení umístění spuštěného spustitelného souboru je v Linuxu a Unixu poměrně složitý a specifický pro platformu. Než to uděláte, měli byste si to dvakrát rozmyslet.
Pokud potřebujete své spustitelné umístění pro zjištění některých konfiguračních nebo zdrojových souborů, možná byste měli postupovat podle unixového způsobu umístění souborů do systému:vložte configs do /etc
nebo /usr/local/etc
nebo v domovském adresáři aktuálního uživatele a /usr/share
je dobré místo pro umístění zdrojových souborů.
Pokud používáte Windows, použijte funkci GetModuleFileName().
Vezměte prosím na vědomí, že následující komentáře jsou pouze pro unix.
Pedantická odpověď na tuto otázku zní, že žádné obecné neexistuje způsob, jak správně odpovědět na tuto otázku ve všech případech. Jak jste zjistili, argv[0] může být rodičovským procesem nastaven na cokoli, a proto nemusí mít žádný vztah ke skutečnému názvu programu nebo jeho umístění v systému souborů.
Často však funguje následující heuristika:
- Pokud je argv[0] absolutní cesta, předpokládejme, že se jedná o úplnou cestu ke spustitelnému souboru.
- Pokud je argv[0] relativní cesta, tj. obsahuje
/
, určete aktuální pracovní adresář pomocí getcwd() a poté k němu připojte argv[0]. - Pokud je argv[0] prosté slovo, prohledejte $PATH a vyhledejte argv[0] a přidejte argv[0] do libovolného adresáře, ve kterém jej najdete.
Všimněte si, že všechny tyto lze obejít procesem, který vyvolal příslušný program. Nakonec můžete použít techniky specifické pro linux, jako je zmíněno emg-2. V jiných operačních systémech pravděpodobně existují ekvivalentní techniky.
I za předpokladu, že výše uvedené kroky vám poskytnou platný název cesty, stále možná nebudete mít název cesty, který skutečně chcete (protože mám podezření, že to, co ve skutečnosti chcete udělat, je někde najít konfigurační soubor). Přítomnost pevných odkazů znamená, že můžete mít následující situaci:
-- assume /app/bin/foo is the actual program
$ mkdir /some/where/else
$ ln /app/bin/foo /some/where/else/foo # create a hard link to foo
$ /some/where/else/foo
Nyní, výše uvedený přístup (včetně, mám podezření, /proc/$pid/exe) dá /some/where/else/foo
jako skutečnou cestu k programu. A ve skutečnosti je to a skutečnou cestu k programu, jen ne tu, kterou jste chtěli. Všimněte si, že tento problém se nevyskytuje u symbolických odkazů, které jsou v praxi mnohem běžnější než pevné odkazy.
Navzdory skutečnosti, že tento přístup je v zásadě nespolehlivý, v praxi pro většinu účelů funguje dostatečně.
Abych to shrnul:
-
V systémech Unix s
/proc
opravdu přímý a spolehlivý způsob je:-
readlink("/proc/self/exe", buf, bufsize)
(Linux) -
readlink("/proc/curproc/file", buf, bufsize)
(FreeBSD) -
readlink("/proc/self/path/a.out", buf, bufsize)
(Solaris)
-
-
Na Unixech bez
/proc
(tj. pokud výše uvedené selže):-
Pokud argv[0] začíná "/" (absolutní cesta), toto je cesta.
-
V opačném případě, pokud argv[0] obsahuje "/" (relativní cesta), přidejte jej do cwd (za předpokladu, že ještě nebylo změněno).
-
Jinak hledejte adresáře v
$PATH
pro spustitelný souborargv[0]
.
Poté může být rozumné zkontrolovat, zda spustitelný soubor není ve skutečnosti symbolický odkaz. Pokud ano, vyřešte jej vzhledem k adresáři symbolických odkazů.
Tento krok není nutný v metodě /proc (alespoň pro Linux). Zde symbolický odkaz proc ukazuje přímo na spustitelný soubor.
Všimněte si, že je na volajícím procesu, aby nastavil
argv[0]
Většinu času je to správné, ale existují případy, kdy volajícímu procesu nelze důvěřovat (např. spustitelný soubor setuid). -
-
V systému Windows:použijte
GetModuleFileName(NULL, buf, bufsize)