質問

私は、環境変数を実装できるプロジェクトのCのシンプルなシェルをプログラムすることです。 GetEnv、Setenv、Putenvの使用方法を調べました。これまでのところ、私はgetENVを使用してシェル変数を表示しようとしました...まあ...いくつかの成功。しかし、私は自分の推論に欠陥があると感じています。私は持っています char** argv ユーザー入力からの解析された入力が含まれています。今すぐ確認してください argv コマンド「エコー」から始まり、次の入力のいずれかがから始まる場合 $ サインかどうか。これが私のコードです:

int executeVariables(char** arguments){
    int i = 0;
    if(strcmp(arguments[i], "echo") == 0){
        char *variable;
        for(i = 1; arguments[i] != NULL; i++){
            char *str = arguments[i];
            if( *(str + 0) == '$'){
                variable = getenv(str + 1);
            }else{
                variable = getenv(str);
            }
            if(!variable){
                //puts("not a variable");
                printf("%s ", arguments[i]);
            }else{
                //puts("a variable");
                printf("%s ", variable);
            }
        }
        printf("\n");
        exit(0);
    }

    return 1;

}

通常のLinuxシェルが見つかったと思います $ サイン、Echoコマンドを呼び出す前に変数を展開します。私のシェルはこの原則に従っていません。エコーコマンド自体の内側の変数を拡大しています。これをどのように実装できるかについてのアイデアはありますか?ありがとう。

編集:

私が抱えている問題は次のとおりです。 echo $HOMEecho HOME 間違っているのと同じ結果を与えてくれます。

編集:

さまざまなテストの後、すべてがうまく機能します。しかし、本当にそれをテストするには、ローカル変数を作成する必要があります echo この値。使用してみました putenv 機能しますが、ローカル変数は作成されません。

i = 0;
char** temp = malloc(sizeof (*temp));
if(strstr(userInput, "=") != NULL){
    //puts("we got equals");
    puts(userInput);
    if(putenv(userInput) == 0){
       printf("doing putenv(%s)\n", userInput);
        exit(0);
    }
    else{
        puts("couldnt putenv");
       exit(1);
    }
}

userInput: char *userInput 入力は、コマンドラインから得られたものです fgets()

役に立ちましたか?

解決

$が見つからない場合でも、文字列に対してgetEnv()を行うようにコードに具体的に求めています。だからそれは$ $ homeまたはhomeを検索します。 Dollar-Signを見つけられないためにElseケースを削除し、その宣言でnullに変数を初期化して、ループ内に配置するようにしてください。

SOのようなもの:

// First, perform replacements
int executeVariables(char** arguments){
    int i = 0;

    for(i = 0; arguments[i] != NULL; i++){
        char *str = arguments[i];

        if(*str == '$'){
            // make sure the result isn't NULL, though I'm not sure a real shell does
            char *tmp = getenv(str + 1);
            if (tmp != NULL) {
                arguments[i] = getenv(str + 1); // save off the argument
            }
        }
    }

    // Then actually execute the function. This would be like bash's echo builtin
    if (strcmp(arguments[0], "echo") == 0) {
        int i;
        for (i = 1; arguments[i] != NULL; i++) {
            printf("%s ", arguments[i]);
        }
        printf("\n");
    }

    // Other functions could go here

    return 1;
}

編集: あなたの方法論に関する限り、なぜあなたは具体的にエコーをチェックするのですか?一般的なものにして、最初の引数を含むすべての引数をチェックしてみませんか?実際には、おそらくすべての潜在的な環境変数を置き換えたいので、MyeCho = Echoがどこかにある場合は、次のことが機能します。より一般的なものにするために、この関数があり、拡張された変数に基づいてものを実行します。あなたはそれをすべて素晴らしくし、個別の機能を持つことができますが、ここにそれをすべて適合させるために、私はそれをテストしていませんが、それに応じて上記のコードを更新しました。 ;)

編集: そうは言っても、これを以前に行うことについてのWedwindleのコメントが適用されます。ここのような引数を置き換えてから、その更新された引数配列を使用して、必要なことを何でもするために別の関数を持たせます。 :)

> $MYVAR totally awesome $HOME
totally awesome /home/user

編集: Putenv()の状況については、次のような構造化されたものが必要です。これにより、シェルやシェルで実行する他のプロセス用に設定されます。

void do_args_env(char *args[])
{
    // do putenv, etc.
}

// inside main loop in shell process
while (1) { // just an example
    if (check_args_syntax(args) != 0) {
        // error
    }

    do_args_env(args);

    // fork and do other stuff
}

(うまくいけば最終)編集: 説明として、プロセスは一般に(おそらくできないでしょうか?)階層の上のプロセスの環境に影響しません。逆の方法だけ。したがって、子供の中にputenv()がいる場合、その子供の兄弟(つまり、親からフォークされた他のプロセス)は環境の変化を得られません。

助けてくれてうれしいです!

他のヒント

はい、通常のシェルは、コマンドラインの解析中に変数を拡張します。したがって、「ユーザー入力からの解析された入力が含まれている」配列を生成する機能の代替変数が必要です。このケースコードで echo (およびその他のコマンド)ははるかに短くなります。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top