Editing Linux Environment Variables in C

Discussion in 'C' started by poornaMoksha, Nov 8, 2011.

  1. poornaMoksha

    poornaMoksha New Member

    Joined:
    Jan 29, 2011
    Messages:
    150
    Likes Received:
    33
    Trophy Points:
    0
    Occupation:
    Software developer
    Location:
    India
    Environment variables can be thought of as a name value pair that affect the behavior of the processes running on an operating system.

    For example, to know the value of environmental variable PATH in my system, I do :

    Code:
    -laptop ~ $ echo $PATH 
     /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
    Now, why do we need environment variables?

    Suppose you created a program that creates some temporary files. The program should create temporary files in some standard path of the system which is used for storing temporary files. Now, your program is not restricted to run on one single computer system. It can run on multiple systems. It is very well possible that the standard path for temporary files is different for different systems. So what would your program do to create temporary files at the standard path for the system its running on??

    Well, in this situation environment variables come to rescue. The program can access the value of corresponding environment variable and creates the temporary files at that path.

    How to access env variables



    Inside the code, the environment variables can be accessed by :

    1) Accepting a third argument 'environ' to the main function.
    Code:
     int main(int argc, char *argv[], char **environ) 
                          OR 
     int main(int argc, char *argv[], char *envp[])
    This way of declaring 'main()' has been deprecated by ISO C.

    2) Accessing a global variable environ.

    This way is preferred over the way described in point 1 above.

    Lets understand the above mentioned ways through an example :

    1) The code below uses the older declaration of main() function to access environment variables :

    Code:
     #include<stdio.h> 
      
     int main(int argc, char *argv[], char *envp[]) 
     { 
         int i = 0; 
      
         while(envp[i] != NULL) 
         { 
             printf("\n [%s] \n",envp[i]); 
             i++; 
         } 
      
         printf("\n Done...exiting\n"); 
      
         return 0; 
     }
    When the above code is run, I get the following output on my machine :

    Code:
      ~/practice $ ./environ  
      
      [ORBIT_SOCKETDIR=/tmp/orbit-himanshu]  
      
      [SSH_AGENT_PID=1695]  
      
      [TERM=xterm]  
      
      [SHELL=/bin/bash]  
      
      [XDG_SESSION_COOKIE=b8b52be9a0280f3c8b48fcf04d7ac5a3-1320743817.969365-1067214140]  
      
      [WINDOWID=20971760]  
      
      [GNOME_KEYRING_CONTROL=/tmp/keyring-aob7hd]  
      
      [GTK_MODULES=canberra-gtk-module]  
      
      [USER=himanshu]  
      
      [SSH_AUTH_SOCK=/tmp/keyring-aob7hd/ssh]  
      
      [DEFAULTS_PATH=/usr/share/gconf/gnome.default.path]  
      
      [SESSION_MANAGER=local/himanshu-laptop:@/tmp/.ICE-unix/1661,unix/himanshu-laptop:/tmp/.ICE-unix/1661]  
      
      [USERNAME=himanshu]  
      
      [XDG_CONFIG_DIRS=/etc/xdg/xdg-gnome:/etc/xdg]  
      
      [DESKTOP_SESSION=gnome]  
      
      [PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games]  
      
      [PWD=/home/himanshu/practice]  
      
      [GDM_KEYBOARD_LAYOUT=us]  
      
      [LANG=en_IN]  
      
      [GNOME_KEYRING_PID=1643]  
      
      [MANDATORY_PATH=/usr/share/gconf/gnome.mandatory.path]  
      
      [GDM_LANG=en_IN]  
      
      [GDMSESSION=gnome]  
      
      [SPEECHD_PORT=7560]  
      
      [SHLVL=1]  
      
      [HOME=/home/himanshu]  
      
      [GNOME_DESKTOP_SESSION_ID=this-is-deprecated]  
      
      [LOGNAME=himanshu]  
      
      [XDG_DATA_DIRS=/usr/share/gnome:/usr/local/share/:/usr/share/]  
      
      [DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-tuOHkHOhpc,guid=5a9c7ce1bf45d031130517354eb8f38a]  
      
      [DISPLAY=:0.0]  
      
      [XAUTHORITY=/var/run/gdm/auth-for-himanshu-UPXg4a/database]  
      
      [COLORTERM=gnome-terminal]  
      
      [_=./environ]  
      
      [OLDPWD=/home/himanshu]  
      
      Done...exiting
    So we can see that all the environment variables for my system are displayed.

    2) The code below uses the global variable 'environ' :

    Code:
     #include<stdio.h> 
      
     extern char **environ; // Need to declare it at least 
     int main(int argc, char *argv[]) 
     { 
         int i = 0; 
      
         while(environ[i] != NULL) 
         { 
             printf("\n [%s] \n",environ[i]); 
             i++; 
         } 
      
         printf("\n Done...exiting\n"); 
      
         return 0; 
     }
    Note that we need to declare the variable 'environ' as extern so that code gets compiled without any errors.
    Now, when I run the code, I get :

    Code:
      ~/practice $ ./environ  
      
      [ORBIT_SOCKETDIR=/tmp/orbit-himanshu]  
      
      [SSH_AGENT_PID=1695]  
      
      [TERM=xterm]  
      
      [SHELL=/bin/bash]  
      
      [XDG_SESSION_COOKIE=b8b52be9a0280f3c8b48fcf04d7ac5a3-1320743817.969365-1067214140]  
      
      [WINDOWID=20971760]  
      
      [GNOME_KEYRING_CONTROL=/tmp/keyring-aob7hd]  
      
      [GTK_MODULES=canberra-gtk-module]  
      
      [USER=himanshu]  
      
      [SSH_AUTH_SOCK=/tmp/keyring-aob7hd/ssh]  
      
      [DEFAULTS_PATH=/usr/share/gconf/gnome.default.path]  
      
      [SESSION_MANAGER=local/himanshu-laptop:@/tmp/.ICE-unix/1661,unix/himanshu-laptop:/tmp/.ICE-unix/1661]  
      
      [USERNAME=himanshu]  
      
      [XDG_CONFIG_DIRS=/etc/xdg/xdg-gnome:/etc/xdg]  
      
      [DESKTOP_SESSION=gnome]  
      
      [PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games]  
      
      [PWD=/home/himanshu/practice]  
      
      [GDM_KEYBOARD_LAYOUT=us]  
      
      [LANG=en_IN]  
      
      [GNOME_KEYRING_PID=1643]  
      
      [MANDATORY_PATH=/usr/share/gconf/gnome.mandatory.path]  
      
      [GDM_LANG=en_IN]  
      
      [GDMSESSION=gnome]  
      
      [SPEECHD_PORT=7560]  
      
      [SHLVL=1]  
      
      [HOME=/home/himanshu]  
      
      [GNOME_DESKTOP_SESSION_ID=this-is-deprecated]  
      
      [LOGNAME=himanshu]  
      
      [XDG_DATA_DIRS=/usr/share/gnome:/usr/local/share/:/usr/share/]  
      
      [DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-tuOHkHOhpc,guid=5a9c7ce1bf45d031130517354eb8f38a]  
      
      [DISPLAY=:0.0]  
      
      [XAUTHORITY=/var/run/gdm/auth-for-himanshu-UPXg4a/database]  
      
      [COLORTERM=gnome-terminal]  
      
      [_=./environ]  
      
      [OLDPWD=/home/himanshu]  
      
      Done...exiting

    How to fetch a particular env variable?



    What if in the code, you want to get value of a particular environment variable ?

    Well, 'getenv()' function is there to help you. The signature of the function is :

    Code:
    char *getenv(const char *name);
    From the man page of this function :

    DESCRIPTION
    The getenv() function searches the environment list to find the environment variable name, and returns a pointer to the corresponding value
    string.

    RETURN VALUE
    The getenv() function returns a pointer to the value in the environment, or NULL if there is no match.​
    Suppose we want to fetch the value of environment variable PATH using this function.

    Lets see how it works :

    Code:
     #include<stdio.h> 
     #include<stdlib.h> 
      
     int main(int argc, char *argv[]) 
     { 
      
         char *val = getenv("PATH"); 
         printf("\nValue of environment variable PATH is [%s]\n",val); 
      
         return 0; 
     }
    When the above code is executed, we see :

    Code:
     $ ./environ  
      
     Value of environment variable PATH is [/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games]
    So we see that through the function 'getenv()' we successfully fetched the value of environment variable PATH. Similarly we can get the value of any environment variable we desire.

    How to set value to a particular env variable?



    What if from within the code you want to create a new environment variable or change value of an existing environment variable?

    Well, this can be done achieved using the 'putenv' or 'setenv' functions.
    From the man page of putenv function :

    NAME
    putenv - change or add an environment variable

    SYNOPSIS
    #include <stdlib.h>

    int putenv(char *string);

    Feature Test Macro Requirements for glibc (see feature_test_macros(7)):

    putenv(): _SVID_SOURCE || _XOPEN_SOURCE

    DESCRIPTION
    The putenv() function adds or changes the value of environment variables. The argument string is of the form name=value. If name does not
    already exist in the environment, then string is added to the environment. If name does exist, then the value of name in the environment is
    changed to value. The string pointed to by string becomes part of the environment, so altering the string changes the environment.

    RETURN VALUE
    The putenv() function returns zero on success, or non-zero if an error occurs.​
    From the man page of setenv function :

    NAME
    setenv - change or add an environment variable

    SYNOPSIS
    #include <stdlib.h>

    int setenv(const char *name, const char *value, int overwrite);

    int unsetenv(const char *name);

    Feature Test Macro Requirements for glibc (see feature_test_macros(7)):

    setenv(), unsetenv(): _BSD_SOURCE || _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600

    DESCRIPTION
    The setenv() function adds the variable name to the environment with the value value, if name does not already exist. If name does exist in the
    environment, then its value is changed to value if overwrite is non-zero; if overwrite is zero, then the value of name is not changed. This func-
    tion makes copies of the strings pointed to by name and value (by contrast with putenv(3)).


    RETURN VALUE
    The setenv() function returns zero on success, or -1 on error, with errno set to indicate the cause of the error. ​
    Lets take a couple of examples as a proof of concept to the above explanations.

    Here is the code which tries to create an environment variable MYENVAR with value /home/himanshu/

    Code:
     #include<stdio.h> 
     #include<stdlib.h> 
      
     int main(int argc, char *argv[]) 
     { 
      
         if(putenv("MYENVAR=/home/himanshu")) 
         { 
             printf("\n putenv() failed\n"); 
             return 1; 
         } 
      
         printf("\n Successfully Added a new environment variable\n"); 
      
         char *val = getenv("MYENVAR"); 
         printf("\nValue of environment variable MYENVAR is [%s]\n",val); 
      
         return 0; 
     }
    When the above code is run, the output we get is :

    Code:
      ~/practice $ ./environ  
      
      Successfully Added a new environment variable 
      
     Value of environment variable MYENVAR is [/home/himanshu]
    So we see that through the function putenv() we successfully added an environment variable to the environment.


    Next up lets try to change the value of existing variable MYENVAR.
    Here is the code to achieve this :

    Code:
     #include<stdio.h> 
     #include<stdlib.h> 
      
     int main(int argc, char *argv[]) 
     { 
      
         char *val = getenv("MYENVAR"); 
         if(val == NULL) 
         { 
             if(putenv("MYENVAR=/home/himanshu")) 
             { 
                 printf("\n putenv() failed\n"); 
                 return 1; 
             } 
             val = getenv("MYENVAR"); 
         } 
         printf("\nCurrent value of environment variable MYENVAR is [%s]\n",val); 
      
         if(putenv("MYENVAR=/home/himanshu/abc")) 
         { 
             printf("\n putenv() failed\n"); 
             return 1; 
         } 
      
         printf("\n Successfully Added a new value to existing environment variable MYENVAR\n"); 
      
         val = getenv("MYENVAR"); 
         printf("\nNew value of environment variable MYENVAR is [%s]\n",val); 
      
      
         return 0; 
     }
    In the above code, we first check whether there already exists an environment variable named MYENVAR. If not then we create one with a value and then we change its value. Now, lets see what happens when we run the above code :

    Code:
     ~/practice $ ./environ  
      
     Current value of environment variable MYENVAR is [/home/himanshu] 
      
      Successfully Added a new value to existing environment variable MYENVAR 
      
     New value of environment variable MYENVAR is [/home/himanshu/abc]
    The output shows that through putenv() function the value of the environment variable is changed easily.

    Now, we can also add/change an environment variable with function setenv(). Lets see how :

    Code:
     #include<stdio.h> 
     #include<stdlib.h> 
      
     int main(int argc, char *argv[]) 
     { 
      
         char *val = getenv("MYENVAR"); 
         if(val == NULL) 
         { 
             if(setenv("MYENVAR","/home/himanshu",0)) 
             { 
                 printf("\n setenv() failed\n"); 
                 return 1; 
             } 
             val = getenv("MYENVAR"); 
         } 
         printf("\nCurrent value of environment variable MYENVAR is [%s]\n",val); 
      
         if(setenv("MYENVAR","/home/himanshu/abc",1)) 
         { 
             printf("\n setenv() failed\n"); 
             return 1; 
         } 
      
         printf("\n Successfuly Added a new value to existing environment variable MYENVAR\n"); 
      
         val = getenv("MYENVAR"); 
         printf("\nNew value of environment variable MYENVAR is [%s]\n",val); 
      
      
         return 0; 
     }
    In the above code, we have used the function setenv() and set the value of third argument as '1' when we wanted to update its value.
    Lets see the output :

    Code:
     ~/practice $ ./environ  
      
     Current value of environment variable MYENVAR is [/home/himanshu] 
      
      Successfully Added a new value to existing environment variable MYENVAR 
      
     New value of environment variable MYENVAR is [/home/himanshu/abc]
    In the above output we see that through setenv() function too we are able to add/modify an environment variable.


    A point worth noting



    Please note that if you set/change an environment variable using the above shown techniques. The persistence of that particular change is temporary. If a new environment variable is added through code, its visibility remains up till the code is running. As soon as the process terminates, the environment variable is cleared.

    To make permanent changes put the new environment string at the end of the .profile, or .bash_rc or .bash_profile file, depending on your distribution.

    Conclusion



    To conclude, this article demonstrates the use of environment variables, how to access them through code. Also, how we can fetch the value or change the value of existing environment variable through C functions.

    Stay tuned for more...
     

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice