How to Access Environment Variables Using setenv Function in C

Jinku Hu Feb 02, 2024
  1. Use the setenv Function to Export Environment Variables in C
  2. Use the envp Variable to Iterate Through Defined Environment Variables in C
  3. Use the environ Variable to Iterate Through Defined Environment Variables in C
How to Access Environment Variables Using setenv Function in C

This article will explain several methods of exporting environment variables using the setenv function in C.

Use the setenv Function to Export Environment Variables in C

Each running program on Unix-base systems has an environment that collects variable-value pairs used mainly by shell and other user space programs. The program can retrieve a single environment variable and its value with the getenv function. But if a new variable should be defined or the existing one changed, the setenv function should be called. It takes three arguments, the first and second of which are char pointers pointing to the variable name and its value, respectively. The third argument is of type int and it specifies whether the value of the given variable should be overwritten if it already exists in the environment. The nonzero value of this argument denotes overwriting behavior and zero value to the opposite.

Note though, iterating through all defined environment variables requires accessing the special global variable called - environ, which is a NULL-terminated array of character strings. Alternatively, one can declare main function with the third argument envp to access variables. In the following example, we print both eniron and envp pointers before and after the setenv function call. Notice that, envp pointer has the same value after the call, whereas environ has been changed.

#include <stdio.h>
#include <stdlib.h>

extern char **environ;

int main(int argc, const char *argv[], const char *envp[]) {
  printf("environ:  %p\n", environ);
  printf("envp:     %p\n", envp);

  setenv("NEW_VAR", "new_value", 1);

  puts("----Added NEW_VAR----");
  printf("environ:  %p\n", environ);
  printf("envp:     %p\n", envp);

  exit(EXIT_SUCCESS);
}

Output:

environ:  0x7fffa05a7fe8
envp:     0x7fffa05a7fe8
----Added NEW_VAR----
environ:  0x5646431276b0
envp:     0x7fffa05a7fe8

Use the envp Variable to Iterate Through Defined Environment Variables in C

The previous code example demonstrates why one should avoid retrieving environment variables using the main function argument envp after calling the setenv function. When the setenv function is called, the environment is relocated, but envp still points to the old environment. The following example code demonstrates the erroneous behavior by defining a new variable with setenv call and then iterating through envp pointer array. Note that we also utilize goto statement to jump to the end of the loop if the variable named NEW_VAR is found.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, const char *argv[], const char *envp[]) {
  if (setenv("NEW_VAR", "new_value", 1) != 0) {
    perror("setenv");
    exit(EXIT_FAILURE);
  }

  if (envp != NULL) {
    for (size_t i = 0; envp[i] != NULL; ++i) {
      if (strcmp(envp[i], "NEW_VAR=new_value") == 0) {
        puts(envp[i]);
        goto END;
      }
    }
    printf("No such variable found!\n");
  }
END:

  exit(EXIT_SUCCESS);
}

Output:

No such variable found!

Use the environ Variable to Iterate Through Defined Environment Variables in C

Since the previous solution can’t find the newly defined variable, we should use the environ variable declared externally. In this case, we included multiple preprocessor conditional statements to make the code portable across the different systems, but only extern char **environ is needed on most UNIX-based systems. Once declared, we can iterate through the list of variables using the same loop we implemented in the previous example.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#if defined(_POSIX_) || defined(__USE_POSIX)
extern char **environ;
#elif defined(_WIN32)
_CRTIMP extern char **_environ;
#endif

int main(void) {
  if (setenv("NEW_VAR", "new_value", 1) != 0) {
    perror("setenv");
    exit(EXIT_FAILURE);
  }

  if (environ != NULL) {
    for (size_t i = 0; environ[i] != NULL; ++i) {
      if (strcmp(environ[i], "NEW_VAR=new_value") == 0) {
        puts(environ[i]);
        goto END;
      }
    }
    printf("No such variable found!\n");
  }
END:

  exit(EXIT_SUCCESS);
}

Output:

NEW_VAR=new_value
Author: 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