C 言語で setenv 関数を使用して環境変数へのアクセス
-
C 言語で関数
setenv
を使って環境変数をエクスポートする -
C 言語で変数
envp
を使って定義された環境変数を反復処理する -
C 言語で環境変数
environ
を使って定義された環境変数を反復処理する
この記事では、C 言語の setenv
関数を使って環境変数をエクスポートするいくつかの方法について説明します。
C 言語で関数 setenv
を使って環境変数をエクスポートする
Unix ベースのシステム上で実行されている各プログラムは、主にシェルや他のユーザ空間プログラムで使用される変数と値のペアを収集する環境を持っています。プログラムは getenv
関数を用いて単一の環境変数とその値を取得することができます。しかし、新しい変数を定義したり、既存の変数を変更したりする場合は setenv
関数を呼び出す必要があります。この関数は 3つの引数をとり、第 1 引数と第 2 引数はそれぞれ変数名とその値を指す char
ポインタです。3 番目の引数は int
型で、与えられた変数の値が環境に既に存在する場合に上書きするかどうかを指定します。この引数の値が 0 以外の場合は上書きの動作を示し、0 の場合はその逆を示します。
ただし、定義されているすべての環境変数を反復処理するには、environ
という特殊なグローバル変数にアクセスする必要があることに注意してください。あるいは、変数にアクセスするために第三引数 envp
を指定して main
関数を宣言することもできます。次の例では、setenv
関数呼び出しの前後に eniron
と envp
の両方のポインタを表示しています。呼び出し後の envp
ポインタの値は同じであるのに対し、environ
ポインタは変更されていることに注目してください。
#include <stdio.h>
#include <stdlib.h>
extern char **environ;
int main(int argc, const char *argv[], const char *envp[]) {
printf("environ: %p\n", environ);
printf("envp: %p\n", envp);
setenv("NEW_VAR", "new_value", 1);
puts("----Added NEW_VAR----");
printf("environ: %p\n", environ);
printf("envp: %p\n", envp);
exit(EXIT_SUCCESS);
}
出力:
environ: 0x7fffa05a7fe8
envp: 0x7fffa05a7fe8
----Added NEW_VAR----
environ: 0x5646431276b0
envp: 0x7fffa05a7fe8
C 言語で変数 envp
を使って定義された環境変数を反復処理する
前のコード例では、setenv
関数を呼び出した後に main
関数の引数 envp
を使って環境変数を取得しないようにする理由を示しています。関数 setenv
が呼び出されると環境は再配置されますが、envp
は古い環境を指したままです。次のコード例は、setenv
を呼び出して新しい変数を定義した後、envp
ポインタの配列を繰り返し実行することで、誤った動作を示しています。また、NEW_VAR
という名前の変数が見つかった場合には、goto
文を使ってループの最後にジャンプしていることに注意してください。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, const char *argv[], const char *envp[]) {
if (setenv("NEW_VAR", "new_value", 1) != 0) {
perror("setenv");
exit(EXIT_FAILURE);
}
if (envp != NULL) {
for (size_t i = 0; envp[i] != NULL; ++i) {
if (strcmp(envp[i], "NEW_VAR=new_value") == 0) {
puts(envp[i]);
goto END;
}
}
printf("No such variable found!\n");
}
END:
exit(EXIT_SUCCESS);
}
出力:
No such variable found!
C 言語で環境変数 environ
を使って定義された環境変数を反復処理する
前の解決策では新たに定義された変数を求めることができなかったので、外部から宣言された environ
変数を使う必要があります。この場合、異なるシステム間でコードを移植可能にするために、複数のプリプロセッサの条件文を含んでいますが、ほとんどの UNIX ベースのシステムでは extern char **environ
だけが必要です。一度宣言されると、前の例で実装したのと同じループを使って、変数のリストを繰り返し実行することができます。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if defined(_POSIX_) || defined(__USE_POSIX)
extern char **environ;
#elif defined(_WIN32)
_CRTIMP extern char **_environ;
#endif
int main(void) {
if (setenv("NEW_VAR", "new_value", 1) != 0) {
perror("setenv");
exit(EXIT_FAILURE);
}
if (environ != NULL) {
for (size_t i = 0; environ[i] != NULL; ++i) {
if (strcmp(environ[i], "NEW_VAR=new_value") == 0) {
puts(environ[i]);
goto END;
}
}
printf("No such variable found!\n");
}
END:
exit(EXIT_SUCCESS);
}
出力:
NEW_VAR=new_value