web-dev-qa-db-ja.com

execveと環境変数の設定の要件を理解する

先生の通訳が大変です。説明を求め、彼から次の返事をもらいました

  1. Execveの場合、エクスポートした変数を使用してセットアップした環境をそれに送信し、/ bin/bashのサブシェルを生成する組み込みコマンドを作成します。これにより、envを使用してエクスポートした変数を確認できます。

    (彼はここで私たち自身の環境変数を作成することについて話しています。)

  2. はい、自分で作成してください。シェルの起動時に環境をコピーし、エクスポートされた変数のみを追加することで開始できます

これは、Stack Overflowに関する次の投稿に関連しています(この他の投稿を読むと、私が何をしようとしているのかを理解するのに役立ちます)。

execveで新しいパスを使用してlsコマンドを実行

これについては非常に混乱しています。もう一度、私たちが今やろうとしていることを説明します。 Linuxシェルがこれを行う方法と同様に、PATHやUSERなどの環境変数や、ユーザーが定義したいその他の変数を設定できる独自のプログラムを作成する必要があります。

これを呼び出す方法の例は次のようになります(プログラム内のプロンプト)。

mysetenv dog spike

「dog = spike」のような環境変数が作成されます

さらに重要なのは、独自のPATH変数を設定してexecコマンドに送信できるようにする必要があることです。すべての質問に基づいて、私たちは何をすべきか理解していないので、これは混乱する部分です。

12
james

それは実際には非常に簡単です。引数が_char *_のリストであり、NULLポインターで終了していることはすでに知っています。同様に、環境は_char *_のリストであり、NULLポインターで終了します。通常、リストの値は_VARNAME=var-value_の形式を取りますが、必要に応じて他の形式を渡すこともできます。

だから、簡単なケースを取るために:

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

int main(void)
{
    char *argv[] = { "/bin/sh", "-c", "env", 0 };
    char *envp[] =
    {
        "HOME=/",
        "PATH=/bin:/usr/bin",
        "TZ=UTC0",
        "USER=beelzebub",
        "LOGNAME=tarzan",
        0
    };
    execve(argv[0], &argv[0], envp);
    fprintf(stderr, "Oops!\n");
    return -1;
}
_

この例では、プログラムは_/bin/sh_を引数_-c_およびenvで実行します。これは、シェルが現在のPATHにあるenvプログラムを実行することを意味します。ここの環境は、正統な形式で5つの値を含むように設定されています。 envdate(または_env; date_)に変更すると、たとえば、TZ設定の効果がわかります。 MacOS Xマシンで実行すると、出力は次のようになります。

_USER=beelzebub
PATH=/bin:/usr/bin
PWD=/Users/jleffler/tmp/soq
TZ=UTC0
SHLVL=1
HOME=/
LOGNAME=tarzan
_=/usr/bin/env
_

シェルは、環境変数SHLVL、___、およびPWDを、execve()呼び出しで明示的に設定したものに追加しました。

また、他の環境変数を、明示的に設定したい環境変数と競合しない本物の環境から他の環境変数にコピーするなど、より洗練された処理を行うこともできます。また、環境内の1つの変数に2つの値を持つようなゲームをプレイすることもできます。どちらが有効になりますか?また、スペースを含む変数名(シェルはそれほど好きではない)、または 'varname = value'表記とまったく一致しないエントリ(等号なし)でゲームをプレイできます。

33

ここでのパーティーには少し遅れますが、古い環境変数を保存して独自の環境変数を作成したい場合は、setenvを使用してからenvironexecve()

_    setenv("dog", "spike", 1);
    extern char** environ;
    execve(argv[0], argv, environ);
_

environは_unistd.h_で宣言された変数であり、この実行プロセス中に環境変数を追跡します。

setenv()putenv()environを変更するため、execve()を介して渡すと、環境変数は期待どおりになります。

5
Fred Frey

Jonathan Lefflerのコードは、PWD(作業ディレクトリ)変数を変更する場合を除いて、うまく機能します。

作業ディレクトリを変更するために私がしたことは、chdir(..)の前にexecve(..)を置き、以下を呼び出すことでした。

chdir("/foo/bar"); 
execve(argv[0], &argv[0], envp);
1
qknight