3

execve を使用して ls コマンドを実行しようとしています。現在、次の引数で実行しています。

execve(args[0], args, env_args)
//args looks like {"ls", "-l", "-a", NULL}
//env_args looks like {"PATH=/bin", "USER=me", NULL}

これが行うことを期待していたのは、新しい env_args を使用して ls コマンドを実行することでした。これは、PATH で ls を検索することを意味します。ただし、このコードは実際には何も実行せず、コードを実行すると出力なしでコマンド プロンプトに戻るだけです。

同じ args[] を使用して、私は execvp を使用していましたが、ls が機能し、現在のパスを検索しました。

私が間違っていることを教えてもらえますか?

私がやろうとしているのは、独自の環境を作成してエクスポートし、char** で定義した環境を exec に使用させることができる独自のシェル プログラムを作成することです。基本的に、env_args を操作して変数を追加および削除する独自の関数を作成しています。exec を呼び出すときに、{"ls", "-l", NULL} で exec を呼び出して新しい環境を調べられるようにしたいと考えています。 ls という有効なプログラムのパス変数。これで私がやっていることが少し良くなることを願っています。この場合、 extern 環境変数が機能するとは思いません。

4

1 に答える 1

11

このexecve()関数は PATH を調べません。そのためには、 が必要execvp()です。あなたのプログラムは の実行に失敗してlsいましたexecve(). . 関数ファミリのメンバーは、exec*()エラー時にのみ戻ることに注意してください。

/bin現在のディレクトリとしてプログラムを実行すると、(多かれ少なかれ) 期待した結果が得られます ( ./ls-別名ls-が存在するため)。

execve()適切な PATH 設定を使用して見つけた後、最初の引数で実行可能ファイルのパス名を指定する必要があります。

または、引き続き を使用しますexecvp()が、変数environを新しい環境に設定します。environどのヘッダーでも宣言されていないという点で、POSIX グローバル変数の中で一意であることに注意してください。

extern char **environ;

environ = env_args;
execvp(args[0], &args[0]);

古い値を保存して復元する必要はありません。あなたは子プロセスにいて、その環境を切り替えてもメインプログラム(シェル)には影響しません。


これは期待どおりに機能しているように見えます。また、元のコードが期待どおりに動作することを示しています。

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

extern char **environ;

int main(void)
{
    char *args[]     = { "ls", "-l", "-a", NULL };
    char *env_args[] = { "PATH=/bin", "USER=me", NULL };

    execve(args[0], args, env_args);
    fprintf(stderr, "Oops!\n");

    environ = env_args;
    execvp(args[0], &args[0]);
    fprintf(stderr, "Oops again!\n");

    return -1;
}

「おっと!」私のディレクトリのリストが続きます。ls現在のディレクトリに実行可能ファイルを作成すると、次のようになります。

#!/bin/sh
echo "Haha!"

それから私は「おっと!」を得ません。「ハハ!」を取得します。

于 2011-10-03T02:25:20.637 に答える