/bin/sh: 0: sh を開けません。

/bin/sh: 0: sh を開けません。

単純なCプログラムを実行しようとしています。

#include <stdio.h>
#include <unistd.h>

extern char** environ;

int main(){
//  execl("/bin/sh","sh","-c","/bin/ls -l",(char *) NULL);
    char* argv[] = {"/bin/sh","sh","-c","/bin/ls", (char*) NULL};
    execve(argv[0], argv, environ);
    return 0;
}

コメントアウトされたexeclはうまく機能します。ただし、execveで同じ操作を実行しようとすると、コンパイラは次のエラーを呼び出します。

/bin/sh: 0: Can't open sh

私がここで何を間違っているのか?

答え1

char* argv[] = {"/bin/sh","sh","-c","/bin/ls", (char*) NULL};
execve(argv[0], argv, environ);

argv[0]()を2回使用してください/bin/sh。一度は最初の引数として使用しexecve()、一度は2番目の引数として渡される配列の一部として使用します。これは呼び出しexecl()で起こるものではなく、/bin/sh最初のパラメータ(プログラムファイル)のみです。

したがって、execve()ファイルを実行して/bin/shプログラム名(0番目の引数)/bin/shと一般的な引数、、sh-c提供します/bin/ls。を呼び出すのとほぼ同じですexecl("/bin/sh", "/bin/sh", "sh", "-c", "/bin/ls", (char*) NULL)。またはシェルコマンドラインから:

$ /bin/sh sh -c /bin/ls
/bin/sh: 0: Can't open sh

これは、シェルに現在のディレクトリで呼び出されたスクリプトを実行するように指示し、shスクリプトが存在しない場合、Dashはエラーメッセージを表示します。 0はコマンドライン引数の行番号です。 (Bashは似ていますが、他のエラーメッセージを提供しており、スクリプトも探しているようです。PATH標準でPATHここでの使用について言及することは不明です。)

あなたはこれを行うことができます

char *program = "/bin/sh";
char *argv[] = {"sh", "-c", "/bin/ls", NULL};
execve(program, argv, environ);

または多分

char *argv[] = {"/bin/sh", "sh", "-c", "/bin/ls", NULL};
execve(argv[0], argv + 1, environ);

関連情報