understanding requirements for execve and setting environment vars

前端 未结 3 515
遇见更好的自我
遇见更好的自我 2021-02-05 15:58

We are having a lot of trouble interpreting our teacher. We asked for clarification and got the following back from him

  1. For execve, send it a environment you se

相关标签:
3条回答
  • 2021-02-05 16:41

    It is actually very simple. You already know that your arguments are a list of char *, terminated by a NULL pointer. Similarly, the environment is simply a list of char *, terminated by a NULL pointer. Conventionally, the values in the list take the form VARNAME=var-value, though you can pass other formats if you wish.

    So, to take a simple case:

    #include <unistd.h>
    #include <stdio.h>
    
    int main(void)
    {
        char *argv[] = { "/bin/sh", "-c", "env", 0 };
        char *envp[] =
        {
            "HOME=/",
            "PATH=/bin:/usr/bin",
            "TZ=UTC0",
            "USER=beelzebub",
            "LOGNAME=tarzan",
            0
        };
        execve(argv[0], &argv[0], envp);
        fprintf(stderr, "Oops!\n");
        return -1;
    }
    

    In this example, the program will run /bin/sh with arguments -c and env, which means that the shell will run the env program found on its current PATH. The environment here is set to contain 5 values in the orthodox format. If you change env to date (or env; date), you will see the effect of the TZ setting, for example. When I run that on my MacOS X machine, the output is:

    USER=beelzebub
    PATH=/bin:/usr/bin
    PWD=/Users/jleffler/tmp/soq
    TZ=UTC0
    SHLVL=1
    HOME=/
    LOGNAME=tarzan
    _=/usr/bin/env
    

    The shell has added environment variables SHLVL, _ and PWD to the ones I set explicitly in the execve() call.

    You can also do fancier things, such as copy in some of the other environment variables from your genuine environment where they do not conflict with the ones you want to set explicitly. You can also play games like having two values for a single variable in the environment - which one takes effect? And you can play games with variable names that contain spaces (the shell doesn't like that much), or entries that do not match the 'varname=value' notation at all (no equals sign).

    0 讨论(0)
  • 2021-02-05 16:47

    I'm a little late to the party here, but if you want to preserve the old environment variables as well as creating your own, use setenv, and then pass environ to execve().

        setenv("dog", "spike", 1);
        extern char** environ;
        execve(argv[0], argv, environ);
    

    environ is a variable declared in unistd.h, and it keeps track of the environment variables during this running process.

    setenv() and putenv() modify environ, so when you pass it over execve(), the environment variables will be just as you'd expect.

    0 讨论(0)
  • 2021-02-05 16:57

    The code from Jonathan Leffler works great, except if you want to change the PWD (working directory) variable.

    What I did, in order to change the working directory, was to put a chdir(..) before execve(..) and call:

    chdir("/foo/bar"); 
    execve(argv[0], &argv[0], envp);
    
    0 讨论(0)
提交回复
热议问题