Get Environment Variable in C++

  1. Use std::getenv Function to Access Environment Variable in C++
  2. 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 <iostream>
#include <string>
#include <cstdlib>

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

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 <iostream>
#include <string>
#include <cstdlib>

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

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 <iostream>
#include <string>
#include <cstdlib>
#include <algorithm>

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

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

}