単純なLinuxシェルの環境変数
-
26-10-2019 - |
質問
私は、環境変数を実装できるプロジェクトの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 $HOME
と echo 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
(およびその他のコマンド)ははるかに短くなります。