Obter Variável de Ambiente em C++
-
Utilizar
std::getenv
Função para aceder à variável de ambiente em C++ - Utilizar rotinas de verificação personalizadas para verificar os valores válidos da variável de ambiente
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);
}
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