Skip to Content
Course content

144: Working with Environment Variables in C

Click on the "Edit" button in the top corner of the screen to edit your slide content.

I've seen this exact crash more times than I care to admit, usually during a late-night debugging session on a production server. You're trying to make your program configurable without hardcoding paths or secrets, so you reach for the environment variables. It seems straightforward, but C doesn't hold your hand here.

# This code looks fine at first glance, right?
#include <stdio.h>
#include <stdlib.h>

int main() {
    char *db_url = getenv("DATABASE_URL");
    printf("Connecting to database at: %s\n", db_url);
    return 0;
}

If you run this on a machine where DATABASE_URL is set, it works perfectly. But the moment you hand this binary to a teammate who hasn't set up their environment, the program crashes with a Segmentation fault. Why? Because getenv() doesn't return an empty string when a variable is missing—it returns NULL. Passing a NULL pointer to printf's %s specifier is a gamble that you're going to lose.

Handling the Missing Variable

The fix is simple, but it's a habit you need to bake into your brain: never trust getenv() to actually find something. You have to validate the pointer before you touch it. I usually handle this by providing a sensible default value so the program can keep running even if the environment isn't perfectly configured.

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

int main() {
    char *db_url = getenv("DATABASE_URL");

    // Check for NULL before using the pointer
    if (db_url == NULL) {
        printf("DATABASE_URL not set. Falling back to localhost...\n");
        db_url = "localhost:5432"; 
    }

    printf("Connecting to database at: %s\n", db_url);
    return 0;
}

Now the program is robust. We've turned a catastrophic crash into a manageable fallback. Note that I didn't use strcpy to move the default value into a buffer; I just pointed db_url to a string literal. This is efficient and safe because we aren't modifying the string.

How C Sees the Environment

Under the hood, the environment is essentially an array of strings, where each string follows the format KEY=VALUE. When you call getenv(), the C standard library searches this array for a string that starts with your key followed by an equals sign. If it finds it, it returns a pointer to the start of the value part of that string.

If you ever need to see everything available to your process—perhaps for a --debug-env flag in your CLI tool—you can't use getenv(). Instead, you use a global variable called environ. It's not defined in a header file, so you have to declare it yourself using extern.

#include <stdio.h>

extern char **environ;

void print_all_env() {
    int i = 0;
    while (environ[i] != NULL) {
        printf("%s\n", environ[i]);
        i++;
    }
}

Be careful with environ. It's a raw pointer to the environment block. While reading it is safe, trying to modify these strings directly is a recipe for disaster. If you need to change a variable for the current process and its children, use setenv(). It handles the memory allocation and resizing of the environment block for you, which is something you really don't want to do manually in C.




📋 Practical Task

Build a Log-Level Filter Utility

Create a small program that simulates a logging system. The program should behave differently based on an environment variable named APP_LOG_LEVEL.

  • If APP_LOG_LEVEL is set to "DEBUG", the program should print: "[DEBUG] Verbose system internals active." and "[INFO] System started."
  • If APP_LOG_LEVEL is set to "INFO" (or if the variable is not set at all), the program should only print: "[INFO] System started."
  • If APP_LOG_LEVEL is set to anything else, the program should print an error message: "Invalid log level provided." and exit with a non-zero status.

Requirements:
Use getenv() to retrieve the variable and strcmp() from <string.h> to compare the values. Ensure your code does not crash when the environment variable is missing.

Rating
0 0

There are no comments for now.

to be the first to leave a comment.