Acessar variáveis de ambiente usando a função setenv em C

  1. Use a função setenv para exportar variáveis ​​de ambiente em C
  2. Use a variável envp para iterar por meio de variáveis ​​de ambiente definidas em C
  3. Use a variável environ para iterar por meio de variáveis ​​de ambiente definidas em C

Este artigo irá explicar vários métodos de exportação de variáveis ​​de ambiente usando a função setenv em C.

Use a função setenv para exportar variáveis ​​de ambiente em C

Cada programa em execução em sistemas baseados em Unix tem um ambiente que coleta pares de valores variáveis ​​usados ​​principalmente por shell e outros programas de espaço do usuário. O programa pode recuperar uma única variável de ambiente e seu valor com a função getenv. Mas se uma nova variável deve ser definida ou a existente alterada, a função setenv deve ser chamada. Leva três argumentos, o primeiro e o segundo dos quais são ponteiros char apontando para o nome da variável e seu valor, respectivamente. O terceiro argumento é do tipo int e especifica se o valor da variável fornecida deve ser sobrescrito se já existir no ambiente. O valor diferente de zero deste argumento denota comportamento de substituição e valor zero para o oposto.

No entanto, observe que a iteração por todas as variáveis ​​de ambiente definidas requer o acesso à variável global especial chamada - environ, que é un array terminada em NULL de cadeias de caracteres. Alternativamente, pode-se declarar a função main com o terceiro argumento envp para acessar variáveis. No exemplo a seguir, imprimimos os ponteiros eniron e envp antes e depois da chamada da função setenv. Observe que, o ponteiro envp tem o mesmo valor após a chamada, enquanto ambi foi alterado.

#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);
}

Resultado:

environ:  0x7fffa05a7fe8
envp:     0x7fffa05a7fe8
----Added NEW_VAR----
environ:  0x5646431276b0
envp:     0x7fffa05a7fe8

Use a variável envp para iterar por meio de variáveis ​​de ambiente definidas em C

O exemplo de código anterior demonstra por que se deve evitar a recuperação de variáveis ​​de ambiente usando o argumento da função main envp depois de chamar a função setenv. Quando a função setenv é chamada, o ambiente é realocado, mas envp ainda aponta para o ambiente antigo. O código de exemplo a seguir demonstra o comportamento errôneo, definindo uma nova variável com a chamada setenv e, em seguida, iterando por meio do array de ponteiro envp. Observe que também utilizamos a instrução goto para pular para o final do loop se a variável chamada NEW_VAR for encontrada.

#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);
}

Resultado:

No such variable found!

Use a variável environ para iterar por meio de variáveis ​​de ambiente definidas em C

Uma vez que a solução anterior não consegue encontrar a variável recém-definida, devemos usar a variável Environment declarada externamente. Nesse caso, incluímos várias instruções condicionais de pré-processador para tornar o código portátil entre os diferentes sistemas, mas apenas extern char **environ é necessário na maioria dos sistemas baseados em UNIX. Depois de declarados, podemos iterar pela lista de variáveis ​​usando o mesmo loop que implementamos no exemplo anterior.

#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);
}

Resultado:

NEW_VAR=new_value