sfun
sfun

Reputation: 308

Accessing Linux environment variables without assigned value

I wrote small convenience functions for working with environment variables in C++ by wrapping std::getenv, setenv and environ. In addition to setting and getting the environment variables, I provided functionality to check if the current environment contains a certain variable.

#include <cstdlib>
#include <unistd.h>

template <typename VAR_TYPE>
void set(const std::string& variableName, VAR_TYPE varValue, bool overwrite = false) {
    if (!setenv(variableName.c_str(), std::string(variableValue).c_str(), overwrite)) {
      if (errno == ENOMEM) {
        throw std::bad_alloc();
      } else if (errno == EINVAL) {
        throw std::invalid_argument("Variable name invalid: "  + variableName);
      } else {
        throw std::runtime_error("Failed to set environment variable " + variableName);
      }
    }
  }

std::string load(const std::string& variableName, const std::string& defaultValue = "") {
    if (const char* envVariable = std::getenv(variableName)) {
      return std::string(envVariable);
    }
    return defaultValue;
  }

bool contains(const std::string& variableName) {
    for (char** currentEnviron = environ; *currentEnviron; currentEnviron++) {
      if (!std::strncmp(variableName.c_str(), *currentEnviron, variableName.length())) {
        return true;
      }
    }
    return false;
  }

However, by definition, this only allows to access environment variables that are in the form NAME=VALUE.

In bash, I can do the following:

$> export SOME_VAR
$> export -p | grep SOME_VAR
declare -x SOME_VAR

Apparently, SOME_VAR is defined somewhere, even if I dont assign a value to it. When I run printenv however, which uses the same methods I use in my wrapper, SOME_VAR is not listed. I have had a look at /proc/self/environ but this only lists variables with assigned value.

My questions are:

  1. What is the difference between an environment variable defined as SOME_VAR_WITH_VALUE=42 and SOME_VAR_WITHOUT_VALUE.
  2. Is there a possibility in C/C++ to access environment variables without values?

Upvotes: 4

Views: 2299

Answers (3)

rustyx
rustyx

Reputation: 85341

Shell has a notion of internal and exported environment variables.

A shell command like ABC=xyz sets an internal variable (which can be seen in Bash using set).

To export an internal variable, there's the export command.

export ABC=xyz will create an internal variable and export it (exported ones can be seen using env).

export ABC by itself does not define any variable, it simple tags ABC to be exported, when it's defined.

Try this for example:

$ ABC=xyz
$ set | grep ABC
ABC=xyz
$ env | grep ABC

And now with export:

$ export ABC
$ set | grep ABC
$ env | grep ABC
$ ABC=xyz
$ set | grep ABC
ABC=xyz
$ env | grep ABC
ABC=xyz

Notice how the variable got exported the moment it was set. So export ABC is purely a shell feature, it does not modify the environment. There is no API for it.

To set an environment variable with an empty value, use export ABC="":

$ export ABC=""
$ env | grep ABC
ABC=

Upvotes: 3

MSalters
MSalters

Reputation: 179809

Ultimately, bash is just another Linux program. There's limited magic involved. It can alter the libc environ variables, but it can also have its own internal variables. If you don't see SOME_VAR_WITHOUT_VALUE in /proc/sef/environ, you can deduce that it's some kind of bash-internal variable.

Note that bash, like most Linux programs, can be run multiple times in parallel. Environments are separate between processes. So even in C you can't access any of the bash environment variables directly. You're taking advantage of the fact that bash copies its environment to your environment, when your process is started. But env -i your_process will stop even that.

Upvotes: 0

TCvD
TCvD

Reputation: 622

First try this:

export SOME_VAR
set | grep SOME_VAR

The second line will return nothing. That is because the first line doesn't define SOME_VAR.

As for your two questions:

  1. export VARIABLE has no effect. It does not create variable with no value, nor does it change value of an already set variable.
  2. Environment variable always has a value, but that value may be empty string. If you try to access nonexistent variable you will get NULL.

Upvotes: 0

Related Questions