How to Get Environment Variable in C++
-
Use
std::getenv
Function to Access Environment Variable in C++ - Use Custom Checking Routines to Verify the Valid Environment Variable Values
This article will explain several methods of how to get the environment variable in C++.
Use std::getenv
Function to Access Environment Variable in C++
getenv
is POSIX compliant function implemented in the C standard library, which can be imported in the C++ source file using the <cstdlib>
header. The function takes the character string as the only argument and searches for the environment variable name that is equal.
Environment variables are conventionally represented with all capital letters, but getenv
still requires the argument string not to have lower case letters as it would not match the variable name even if it’s defined in the program environment. The function returns the char*
type where the corresponding variable value is stored.
Notice that we assign the return value of the getenv
to const char*
variable because we need to ensure the program does not modify that location; otherwise, it will result in undefined behavior.
#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);
}
Output:
HOME : /home/username
It is also important not to pass the value returned from the getenv
function directly to the std::string
constructor, as it might throw a segmentation fault when the getenv
function fails to math any environment variable.
This issue is caused here within the implementation of the std::string
constructor code which calls the function std::char_traits::length()
underneath the hood. The latter function will cause undefined behavior if nullptr
is passed to it as an argument. Thus, there’s the scenario where getenv
can return nullptr
when the environment variable is not found, and if we pass it to the string
constructor, the erroneous code is formed.
#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);
}
Use Custom Checking Routines to Verify the Valid Environment Variable Values
One of the most dangerous pitfall when accessing the environment variables is verifying the retrieved value. Note that these variables may be manipulated by the attacker outside the scope of our program. Thus, there needs to be additional sanitization of these values to ensure correct and secure program execution.
These checking routines are mostly program dependent and should be handled differently for each case. In the following example, we demonstrate the scenario where we assume that the string value should not have any spaces in it and if it does we extract the substring before the first space character. In this way, we evade any irregular input values from the system environment. Notice that, std::find
algorithm is utilized to search for a character in the string
, and it returns string::npos
if the specified char
is not found.
#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