簡単な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
ここで何が悪いのですか?
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);