Obter Variável de Ambiente em C++

Jinku Hu 12 outubro 2023
  1. Utilizar std::getenv Função para aceder à variável de ambiente em C++
  2. Utilizar rotinas de verificação personalizadas para verificar os valores válidos da variável de ambiente
Obter Variável de Ambiente em C++

Este artigo irá explicar vários métodos de como obter a variável ambiente em C++.

Utilizar std::getenv Função para aceder à variável de ambiente em C++

getenv é uma função compatível com POSIX implementada na biblioteca padrão C, que pode ser importada no ficheiro fonte C++ utilizando o cabeçalho <cstdlib>. A função toma a string como o único argumento e procura o nome da variável de ambiente que é igual.

As variáveis de ambiente são convencionalmente representadas com todas as letras maiúsculas, mas getenv ainda requer que a string de argumentos não tenha letras minúsculas, pois não corresponderia ao nome da variável mesmo que fosse definida no ambiente do programa. A função retorna o tipo char* onde o valor da variável correspondente é armazenado.

Note que atribuímos o valor de retorno da variável getenv a const char* porque precisamos de assegurar que o programa não modifica essa localização; caso contrário, resultará num comportamento indefinido.

#include <cstdlib>
#include <iostream>
#include <string>

using std::cerr;
using std::cout;
using std::endl;
using std::getenv;
using std::string;

const char *ENV_VAR = "HOME";

int main() {
  const char *tmp = getenv("HOME");
  string env_var(tmp ? tmp : "");
  if (env_var.empty()) {
    cerr << "[ERROR] No such variable found!" << endl;
    exit(EXIT_FAILURE);
  }

  cout << "HOME : " << env_var << endl;

  exit(EXIT_SUCCESS);
}

Resultado:

HOME : /home/username

Também é importante não passar o valor retornado da função getenv directamente para o construtor std::string, uma vez que pode causar um erro de segmentação quando a função getenv não consegue fazer contas com qualquer variável de ambiente.

Este problema é causado aqui dentro da implementação do código construtor std::string que chama à função std::char_traits::length() debaixo do capô. Esta última função causará um comportamento indefinido se nullptr lhe for passado como argumento. Assim, há o cenário em que getenv pode retornar nullptr quando a variável de ambiente não é encontrada, e se a passarmos ao construtor string, o código erróneo é formado.

#include <cstdlib>
#include <iostream>
#include <string>

using std::cerr;
using std::cout;
using std::endl;
using std::getenv;
using std::string;

const char *ENV_VAR = "HOME";

int main() {
  // Erroneous
  string env_var(getenv("HOME"));
  if (env_var.empty()) {
    cerr << "[ERROR] No such variable found!" << endl;
    exit(EXIT_FAILURE);
  }

  cout << "HOME : " << env_var << endl;

  exit(EXIT_SUCCESS);
}

Utilizar rotinas de verificação personalizadas para verificar os valores válidos da variável de ambiente

Uma das armadilhas mais perigosas ao aceder às variáveis ambientais é a verificação do valor recuperado. Note-se que estas variáveis podem ser manipuladas pelo atacante fora do âmbito do nosso programa. Assim, é necessário que haja uma sanitização adicional destes valores para assegurar a execução correcta e segura do programa.

Estas rotinas de verificação são na sua maioria dependentes do programa e devem ser tratadas de forma diferente para cada caso. No exemplo seguinte, demonstramos o cenário em que assumimos que o valor da string não deve ter quaisquer espaços e se o fizer extraímos o substrato antes do primeiro carácter de espaço. Desta forma, evitamos qualquer valor de inteiro irregular do ambiente do sistema. Note que, o algoritmo std::find é utilizado para procurar um carácter na string, e retorna string::npos se o char especificado não for encontrado.

#include <algorithm>
#include <cstdlib>
#include <iostream>
#include <string>

using std::cerr;
using std::cout;
using std::endl;
using std::find;
using std::getenv;
using std::string;

const char *ENV_VAR = "HOME";

int main() {
  const char *tmp = getenv(ENV_VAR);
  string env_var(tmp ? tmp : "");
  if (env_var.empty()) {
    cerr << "[ERROR] No such variable found!" << endl;
    exit(EXIT_FAILURE);
  }

  // Env Variable Value Sanitization
  int pos = env_var.find(' ');
  if (pos != string::npos) env_var = env_var.substr(0, pos);

  cout << "HOME : " << env_var << endl;

  exit(EXIT_SUCCESS);
}
Autor: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.

LinkedIn Facebook