使用C代码获取环境变量

时间:2022-06-29 23:13:04

Here I wrote a C program which executes hi.sh file using system call.

在这里,我写了一个C程序,它使用系统调用执行hi.sh文件。

Here I used . ./hi.sh so I want to execute this script in the same shell and then try to get environment variable using getenv function, but here I am getting different output from what I expected.

在这里我用过。 ./hi.sh所以我想在同一个shell中执行这个脚本,然后尝试使用getenv函数获取环境变量,但是在这里我得到了我预期的不同输出。

The hi.sh file contains

hi.sh文件包含

export TEST=10
return

Means when I run this hi.sh file using system call, its export TEST sets the value to 10 in same shell. After this, I am trying to get this variable value but its given NULL value.

表示当我使用系统调用运行此hi.sh文件时,其导出TEST在同一个shell中将值设置为10。在此之后,我试图获取此变量值但其给定的NULL值。

And if I run this script manually from console like . ./hi.sh then it works fine and I get 10 value of TEST using getenv("TEST") function.

如果我从控制台手动运行此脚本。 ./hi.sh然后它工作正常,我使用getenv(“TEST”)函数获得10个TEST值。

Code:

码:

#include <stdio.h>
int main()
{
    system(". ./hi.sh");
    char *errcode;
    char *env = "TEST";
    int errCode;    
    errcode = getenv(env);
    printf("Value is = %s\n",errcode);
    if (errcode != NULL) {
        errCode =atoi(errcode);
        printf("Value is = %d\n",errCode);
    }
}

output :

输出:

Value is = (null)

How can I export TEST variable in program shell? If system() executes commands in different shell then how can I use C program code to get an environment variable which is exported by the shell invoked via a system() call?

如何在程序shell中导出TEST变量?如果system()在不同的shell中执行命令,那么我如何使用C程序代码来获取由system()调用调用的shell导出的环境变量?

4 个解决方案

#1


7  

As usual, the man page does explain this, but you need to read it very carefully.

与往常一样,手册页确实解释了这一点,但您需要非常仔细地阅读它。

DESCRIPTION
       system()  executes a command specified in command by calling /bin/sh -c
       command, and returns after the command has been completed.  During exe‐
       cution  of the command, SIGCHLD will be blocked, and SIGINT and SIGQUIT
       will be ignored.

In other words, system() first starts /bin/sh, and then has /bin/sh start whatever command you want to execute. So what happens here is that the TEST variable is exported to the /bin/sh shell the system() call implicitly started, but not to the program which called system().

换句话说,system()首先启动/ bin / sh,然后让/ bin / sh启动你想要执行的任何命令。那么这里发生的是TEST变量被导出到/ bin / sh shell,system()调用是隐式启动的,而不是调用system()的程序。

#2


9  

The child process cannot directly set the parent process's environment. The approach using system() and getenv() is doomed to fail, therefore.

子进程无法直接设置父进程的环境。因此,使用system()和getenv()的方法注定要失败。

If you are trying to import selected variables set by the script hi.sh, then you have a couple of choices. Either you can read the script hi.sh and work out what it would set them to (rather hard), or you can run the script and have the code you run report back on the environment variables of interest.

如果您尝试导入脚本hi.sh设置的选定变量,那么您有几个选择。您可以阅读脚本hi.sh并找出它将它们设置为什么(相当难),或者您可以运行脚本并让您运行的代码报告回感兴趣的环境变量。

Suppose that hi.sh sets $ENV1 and $ENV2. You can use popen() to get the values back to your program, and setenv() to set your program's environment. In outline:

假设hi.sh设置$ ENV1和$ ENV2。您可以使用popen()将值返回给程序,并使用setenv()来设置程序的环境。概述:

FILE *fp = popen(". ./hi.sh; echo ENV1=$ENV1; echo ENV2=$ENV2", "r");

while (fgets(buffer, sizeof(buffer), fp) != 0)
{
    ...split the buffer into env_name, env_value...
    setenv(env_name, env_value);
}

pclose(fp);

Note that I included the variable name in the echoed information; this simplifies life. If your list of variables gets unwieldy, maybe you run ". ./hi.sh; env" to get the entire environment, and then read each line and work out from your built-in list whether its a variable setting you want to use or not. Or you can simply set your entire environment again, if that pleases you. You should check that the setenv() function succeeded (it returns zero when it does succeed). You should also check that the popen() was successful (fp != 0). In this context, you probably can use strtok() to look for the = separating the variable name from the value; it tramples a null byte over the =, giving you a null terminated name and a null terminated value:

请注意,我在变换的信息中包含了变量名称;这简化了生活。如果您的变量列表变得难以处理,可能运行“./hi.sh; env”来获取整个环境,然后读取每一行并从内置列表中找出它是否是您要使用的变量设置或不。或者你可以简单地再次设置你的整个环境,如果那让你高兴的话。你应该检查setenv()函数是否成功(当它成功时返回零)。你还应该检查popen()是否成功(fp!= 0)。在这种情况下,您可以使用strtok()来查找=将变量名与值分开;它在=上遍历一个空字节,给你一个空终止名称和一个空终止值:

    char *env_name = strtok(buffer, "=");
    char *env_value = buffer + strlen(env_name) + 1;
    if (setenv(env_name, env_value) != 0)
        ...report trouble...

#3


1  

Another possible solution is to have your program exec itself through another shell. That shell replace the running program, then read the environment variables and then replace shell with a new copy of the program. You need to tell the new copy that it has already done an exec or it will just loop doing it over and over. You could look for the environment variable, or pass a command-line flag.

另一种可能的解决方案是让你的程序通过另一个shell执行。该shell替换正在运行的程序,然后读取环境变量,然后用程序的新副本替换shell。你需要告诉新副本它已经完成了一个exec,或者它只是一遍又一遍地循环执行它。您可以查找环境变量,或传递命令行标志。

An untested example:

一个未经测试的例子:

execl("/bin/sh", "-c", ". ./hi.sh; exec ./a.out --envset", NULL);

You would need to replace a.out with whatever the real program name is. You would probably want to extract it from argv[0] and also pass the rest of the argv array. But you have to reformat the arguments to work as shell arguments, so they need to be quoted as necessary, etc.

您需要将a.out替换为真正的程序名称。您可能希望从argv [0]中提取它并传递argv数组的其余部分。但是你必须重新格式化参数以作为shell参数工作,因此需要根据需要引用它们等。

#4


0  

You can either set the environment variable in your own process using setenv() (which system() then silently passes on to child processes, or explicitly pass the variables by using fork() and execve() to run the shell script.

您可以使用setenv()在自己的进程中设置环境变量(system()然后以静默方式传递给子进程,或者使用fork()和execve()显式传递变量来运行shell脚本。

#1


7  

As usual, the man page does explain this, but you need to read it very carefully.

与往常一样,手册页确实解释了这一点,但您需要非常仔细地阅读它。

DESCRIPTION
       system()  executes a command specified in command by calling /bin/sh -c
       command, and returns after the command has been completed.  During exe‐
       cution  of the command, SIGCHLD will be blocked, and SIGINT and SIGQUIT
       will be ignored.

In other words, system() first starts /bin/sh, and then has /bin/sh start whatever command you want to execute. So what happens here is that the TEST variable is exported to the /bin/sh shell the system() call implicitly started, but not to the program which called system().

换句话说,system()首先启动/ bin / sh,然后让/ bin / sh启动你想要执行的任何命令。那么这里发生的是TEST变量被导出到/ bin / sh shell,system()调用是隐式启动的,而不是调用system()的程序。

#2


9  

The child process cannot directly set the parent process's environment. The approach using system() and getenv() is doomed to fail, therefore.

子进程无法直接设置父进程的环境。因此,使用system()和getenv()的方法注定要失败。

If you are trying to import selected variables set by the script hi.sh, then you have a couple of choices. Either you can read the script hi.sh and work out what it would set them to (rather hard), or you can run the script and have the code you run report back on the environment variables of interest.

如果您尝试导入脚本hi.sh设置的选定变量,那么您有几个选择。您可以阅读脚本hi.sh并找出它将它们设置为什么(相当难),或者您可以运行脚本并让您运行的代码报告回感兴趣的环境变量。

Suppose that hi.sh sets $ENV1 and $ENV2. You can use popen() to get the values back to your program, and setenv() to set your program's environment. In outline:

假设hi.sh设置$ ENV1和$ ENV2。您可以使用popen()将值返回给程序,并使用setenv()来设置程序的环境。概述:

FILE *fp = popen(". ./hi.sh; echo ENV1=$ENV1; echo ENV2=$ENV2", "r");

while (fgets(buffer, sizeof(buffer), fp) != 0)
{
    ...split the buffer into env_name, env_value...
    setenv(env_name, env_value);
}

pclose(fp);

Note that I included the variable name in the echoed information; this simplifies life. If your list of variables gets unwieldy, maybe you run ". ./hi.sh; env" to get the entire environment, and then read each line and work out from your built-in list whether its a variable setting you want to use or not. Or you can simply set your entire environment again, if that pleases you. You should check that the setenv() function succeeded (it returns zero when it does succeed). You should also check that the popen() was successful (fp != 0). In this context, you probably can use strtok() to look for the = separating the variable name from the value; it tramples a null byte over the =, giving you a null terminated name and a null terminated value:

请注意,我在变换的信息中包含了变量名称;这简化了生活。如果您的变量列表变得难以处理,可能运行“./hi.sh; env”来获取整个环境,然后读取每一行并从内置列表中找出它是否是您要使用的变量设置或不。或者你可以简单地再次设置你的整个环境,如果那让你高兴的话。你应该检查setenv()函数是否成功(当它成功时返回零)。你还应该检查popen()是否成功(fp!= 0)。在这种情况下,您可以使用strtok()来查找=将变量名与值分开;它在=上遍历一个空字节,给你一个空终止名称和一个空终止值:

    char *env_name = strtok(buffer, "=");
    char *env_value = buffer + strlen(env_name) + 1;
    if (setenv(env_name, env_value) != 0)
        ...report trouble...

#3


1  

Another possible solution is to have your program exec itself through another shell. That shell replace the running program, then read the environment variables and then replace shell with a new copy of the program. You need to tell the new copy that it has already done an exec or it will just loop doing it over and over. You could look for the environment variable, or pass a command-line flag.

另一种可能的解决方案是让你的程序通过另一个shell执行。该shell替换正在运行的程序,然后读取环境变量,然后用程序的新副本替换shell。你需要告诉新副本它已经完成了一个exec,或者它只是一遍又一遍地循环执行它。您可以查找环境变量,或传递命令行标志。

An untested example:

一个未经测试的例子:

execl("/bin/sh", "-c", ". ./hi.sh; exec ./a.out --envset", NULL);

You would need to replace a.out with whatever the real program name is. You would probably want to extract it from argv[0] and also pass the rest of the argv array. But you have to reformat the arguments to work as shell arguments, so they need to be quoted as necessary, etc.

您需要将a.out替换为真正的程序名称。您可能希望从argv [0]中提取它并传递argv数组的其余部分。但是你必须重新格式化参数以作为shell参数工作,因此需要根据需要引用它们等。

#4


0  

You can either set the environment variable in your own process using setenv() (which system() then silently passes on to child processes, or explicitly pass the variables by using fork() and execve() to run the shell script.

您可以使用setenv()在自己的进程中设置环境变量(system()然后以静默方式传递给子进程,或者使用fork()和execve()显式传递变量来运行shell脚本。