web-dev-qa-db-ja.com

/ 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

ここで何が悪いのですか?

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

argv[0]/bin/sh)を2回使用していることに注意してください。1回はexecve()の最初の引数として、もう1回は配列の一部として2番目の引数として渡されます。これはexecl()の呼び出しで発生するものではなく、最初の引数(プログラムファイル)として/bin/shしかありません。

したがって、execve()はファイル/bin/shを実行し、/bin/shのプログラム名(0番目の引数)と通常の引数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がエラーメッセージを表示します。ゼロはおそらくコマンドライン引数の行番号です。 (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);
11
ilkkachu