Reading environment variables
Another way to communicate with the shell—and to configure a program—is via environment variables. By default, there are a lot of environment variables already set. These variables contain information on just about anything regarding your user and your settings. Some examples include the username, which type of terminal you are using, the path variable we discussed in previous recipes, your preferred editor, your preferred locale and language, and more.
Knowing how to read these variables will make it much easier for you to adapt your programs to the user's environment.
In this recipe, we will write a program that reads environment variables, adapts its output, and prints some information about the user and the session.
Getting ready
For this recipe, we can use just about any shell. Other than a shell, we'll need the GCC compiler.
How to do it…
Follow these steps to write a program that reads environment variables:
- Save the following code into a file called
env-var.c
. You can also download the whole program from https://github.com/PacktPublishing/Linux-System-Programming-Techniques/blob/master/ch2/env-var.c. This program will read some common environment variables from your shell using thegetenv()
function. The strange-looking number sequences (\033[0;31
) are used to color the output:#include <stdio.h> #include <stdlib.h> #include <string.h> int main(void) {    /* Using getenv() to fetch env. variables */    printf("Your username is %s\n", getenv("USER"));    printf("Your home directory is %s\n",       getenv("HOME"));    printf("Your preferred editor is %s\n",       getenv("EDITOR"));    printf("Your shell is %s\n", getenv("SHELL"));    /* Check if the current terminal support colors*/    if ( strstr(getenv("TERM"), "256color")  )    {       /* Color the output with \033 + colorcode */       printf("\033[0;31mYour \033[0;32mterminal "          "\033[0;35msupport "          "\033[0;33mcolors\033[0m\n");    }    else    {       printf("Your terminal doesn't support"          " colors\n");    }    return 0; }
- Compile the program using GCC:
$> gcc env-var.c -o env-var
- Run the program. The information that will be printed for you will differ from mine. The last line will also be in color if your terminal supports it. If it doesn't, it will tell you that your terminal doesn't support colors:
$> ./env-var Your username is jake Your home directory is /home/jake Your preferred editor is vim Your shell is /bin/bash Your terminal support colors
- Let's investigate the environment variables we used by using
echo
. Make a note of the$TERM
variable. The dollar sign ($
) tells the shell that we want to print theTERM
variable, not the word TERM:$> echo $USER jake $> echo $HOME /home/jake $> echo $EDITOR vim $> echo $SHELL /bin/bash $> echo $TERM screen-256color
- If we were to change the
$TERM
variable to a regularxterm
, without color support, we would get a different output from the program:$> export TERM=xterm $> ./env-var Your username is jake Your home directory is /home/jake Your preferred editor is vim Your shell is /bin/bash Your terminal doesn't support colors
- Before moving on, we should reset our terminal to the value it was before we changed it. This will probably be something else on your computer:
$> export TERM=screen-256color
- It's also possible to set an environment variable temporarily for the duration of the program. We can do this by setting the variable and executing the program on the same line. Notice that when the program ends, the variable is still the same as it was previously. We just override the variable when the program executes:
$> echo $TERM xterm-256color $> TERM=xterm ./env-var Your username is jake Your home directory is /home/jake Your preferred editor is vim Your shell is /bin/bash Your terminal doesn't support colors $> echo $TERM xterm-256colo
- We can also print a complete list of all the environment variables using the
env
command. The list will probably be several pages long. All of these variables can be accessed using thegetenv()
C function:$> env
How it works…
We use the getenv()
function to get the values from the shell's environment variables. We print these variables to the screen.
Then, at the end of the program, we check if the current terminal has color support. This is usually denoted by something such as xterm-256color
, screen-256color
, and so on. We then use the strstr()
function (from string.h
) to check if the $TERM
variable contains the 256color
substring. If it does, the terminal has color support, and we print a colorized message on the screen. If it doesn't, however, we print that the terminal doesn't have color support, without using any colors.
All of these variables are the shell's environment variables and can be printed with the echo
command; for example, echo $TERM
. We can also set our own environment variables in the shell; for instance, export FULLNAME=Jack-Benny
. Likewise, we can change existing ones by overwriting them, just as we did with the $TERM
variable. We can also override them by setting them at runtime, like we did with TERM=xterm ./env-var
.
Regular variables set with the FULLNAME=Jack-Benny
syntax are only available to the current shell and are hence called local variables. When we set variables using the export
command, they become global variables or environment variables, a more common name, available to both subshells and child processes.
There's more…
We can also change environment variables and create new ones in a C program by using the setenv()
function. However, when we do so, those variables won't be available in the shell that started the program. The program we run is a child process of the shell, and hence it can't change the shell's variable; that is, its parent process. But any other programs started from inside our own program will be able to see those variables. We will discuss parent and child processes in more depth later in this book.
Here is a short example of how to use setenv()
. The 1
in the third argument to setenv()
means that we want to overwrite the variable if it already exists. If we change it to a 0
, it prevents overwriting:
env-var-set.c
#define _POSIX_C_SOURCE 200112L #include <stdio.h> #include <stdlib.h> int main(void) { Â Â Â Â setenv("FULLNAME", "Jack-Benny", 1); Â Â Â Â printf("Your full name is %s\n", getenv("FULLNAME")); Â Â Â Â return 0; }
If we compile and run the program and then try to read $FULLNAME
from the shell, we'll notice that it doesn't exist:
$> gcc env-var-set.c -o env-var-set $> ./env-var-set Your full name is Jack-Benny $> echo $FULLNAME