空の環境で実行ファイルを見つける方法は?

空の環境で実行ファイルを見つける方法は?

実験目的で、次のように$PATH印刷して呼び出すバイナリを作成しました。which

#include <stdlib.h>
#include <stdio.h>

int main() {
    char *path = getenv("PATH");

    if (path)
        printf("got a path: %s\n", path);
    else
        printf("got no path\n");

    system("which which");
    return 0;
}

空の環境で実行したとき

env -i ./printpath

私は次のような印刷物を取得します。

got no path
/usr/bin/which

私の質問は次のとおりですwhichそうでなくても正しいバイナリが呼び出されるのはなぜですか$PATH

答え1

functionを使用したので、system別のシェルを使用してコマンドを実行しますwhich which。からman system

DESCRIPTION
       system()  executes a command specified in command by calling /bin/sh -c
       command, and returns after the command has been completed.  During exe‐
       cution  of the command, SIGCHLD will be blocked, and SIGINT and SIGQUIT
       will be ignored.

which whichコマンドを次のように変更した場合echo $PATH

$ env -i ./a.out 
got no path
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

execve代わりに使用するようにコードを変更すると、system予想される出力が得られます。

#include <stdlib.h>                                                             
#include <stdio.h>  

int main() {                                                                    
    char *path = getenv("PATH");                                                

    if (path)                                                                   
        printf("got a path: %s\n", path);                                       
    else                                                                        
        printf("got no path\n");                                                

    execve("echo $PATH");                                                       
    return 0;                                                                   
} 

コンパイルして実行します。

$ gcc test.c && env -i ./a.out 
got no path

答え2

空の環境では、フルパスを指定しないと実行可能ファイルが見つかりません。試してみてくださいexecvp

このsystem関数はシェルを呼び出します。 Linuxでは、Glibcを使用してシェルを呼び出します/bin/sh(したがってPATH必要ありません)。環境の変数に加えて、シェルは独自の変数の一部を定義します。これを実行して定義した内容とenv -i /path/to/shell -c set実行してエクスポートする内容を表示できますenv -i /path/to/shell -c export。具体的には、dash と bash (Linux で見つけることができる 2 つのシェル) は、/bin/sh環境にない場合は「一般」デフォルトに設定されます (エクスポートできません)。PATH他のシェルは異なる値を設定したり、まったく設定しません。

$ env -i bash -c 'echo $PATH'
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
$ env -i dash -c 'echo $PATH'
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
$ env -i mksh -c 'echo $PATH'
/usr/bin:/bin
$ env -i ksh93 -c 'echo $PATH'

$ env -i zsh -c 'echo $PATH' 
/bin:/usr/bin:/usr/ucb:/usr/local/bin
$ env -i csh -c 'echo $PATH' 
PATH: Undefined variable.
$ env -i tcsh -c 'echo $PATH'
PATH: Undefined variable.

私のコンピュータでは(そして明らかにあなたのコンピュータでも同じです)whichそれ/bin/sh自体がスクリプトです。呼び出しシェルはプログラムsystemを見つけるために独自のパス変数を使用しwhichますが、エクスポートしません。スクリプト自体を実行するシェルは、内部使用のための変数whichも定義します。PATH

関連情報