Ta funkce je zduplikovaná v shellu, libc, v jádře.
Shell normálně najde (vytáhne z předpřipravené hash mapy) cestu k programu a to předá jedné z libc exec funkcí, která to verbatim předá jadernému execvpe (např) syscallu.
Knihovní exec může ale volat i někdo jiný a nepředat úplnou cestu, potom to v PATH hledá implementace v libc (hezky čitelně to je v musl src/process/execvp.c).
A taky může někdo přímo zavolat exec syscall bez úplné cesty, a nebo spustit skript jehož #! nemá úplnou cestu. Pak je na jádře, aby si to našlo samo.
9. 1. 2024, 12:22 editováno autorem komentáře
U konfigurace systémových služeb to je rozumné rozhodnutí – nebo opačně, je špatně v takovém případě spoléhat na $PATH
, jejíž obsah ani neznáte. Kolik bylo jenom tady ve fóru dotazů, kdy někdo řešil, že mu něco nefunguje z cronu nebo init skriptu, a když to spustí ručně, funguje mu to – a problém byl to, že spouštěl něco z $PATH
, ve svém prostředí to měl, ale cron nebo init skript měl mnohem menší $PATH
a daná věc tam prostě nebyla.
Taky mě to překvapilo. Pak jsem kouknul na patch a on jenom optimalizuje pořadí operací - místo kopírování argumentů and environment a poté exec filename lookup provede nejdřív filename lookup a pokud selže, tak rovnou vrátí chybu a ostatní drahé operace přeskočí.
Takže klasický exec zůstává pořád implementovaný v libc a zkouší postupně všechny cesty. Chytřejší shelly si "úspěšnou" path cachují.