带有列出环境变量的 exec() 函数

exec() function with listing environment variables

此代码用于程序 "echoall":

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

int main(int argc, char** argv)
{
        int i;
        char **ptr;
        extern char **environ;

        for(i=0; i<argc; i++)
                printf("argv[%d]: %s \n", i, argv[i]);

        for(ptr=environ; *ptr!=0; ptr++)
        {
                printf("%s \n", *ptr);
        }

        exit(0);
}

此代码适用于使用 exec() 调用的程序:

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/wait.h>

char *env_init[]={"USER=unknown", "PATH=/tmp", NULL};

int main(void)
{
        //extern char **environ;
        //char **ptr;
        pid_t pid;

        //for(ptr=environ; *ptr!=0; ptr++)
        //      printf("%s\n", *ptr);

        if((pid==fork()) < 0 )
        {
                printf("fork() error");
                exit(1);
        }
        else if(pid==0)
        {
                if(execle("/root/apue/chapter_8/echoall", "echoall", "myarg1", "MY ARG2", (char*)0, env_init)<0)
                {
                        printf("execle() error");
                        exit(1);
                }
        }

        if(waitpid(pid, NULL, 0) < 0)
        {
                printf("wait error");
                exit(1);
        }

        if((pid=fork())<0)
        {
                printf("fork() error");
                exit(1);
        }
        else if(pid==0)
        {
                if(execlp("echoall", "only 1 arg", (char*)0)<0)
                {
                        printf("execlp() error");
                        exit(1);
                }
        }

        exit(0);
}

当我们使用exec()接收环境列表参数的函数时,这些环境列表就是执行程序的环境列表(这里,第一个fork())。

但是当我们使用不接收环境列表参数的exec()函数时,父类的char **environ会自动用于执行的程序。 (在这里,第二个 fork()

所以,结果应该是第一个 "echoall" 程序的环境是:

USER=unknwon PATH=/tmp

并且,第二个 "echoall" 程序的环境与父程序的环境列表相同。 但是,我的结果显示与第一个 "echoall" 程序的环境列表相同:

USER=unknown PATH=/tmp

我在 shell 提示符下执行使用 fork()(不是 "echoall" 程序)的程序。所以第二个 "echoall" 程序应该输出与 shell 相同的环境列表。(因为使用 fork() 的程序也继承了 shell 的环境列表)。

这里有什么问题?

并且,当程序在上面的擦除注释中使用 fork()(这意味着它显示其环境列表。)时,waitpid() 函数 return -1,所以我得到错误?为什么会这样?

在 glibc 周围追了一段时间后,我终于注意到 gcc 一直试图告诉我的内容:

2.c: In function 'main':
2.c:22:16: warning: 'pid' is used uninitialized in this function [-Wuninitialized]
         else if(pid==0)

上面的代码有 if((pid==fork()) < 0 ),应该是 if ((pid=fork()) < 0)。一旦我改变了它,一切都按预期工作......

$ env -i A=1 ./2
argv[0]: echoall 
argv[1]: myarg1 
argv[2]: MY ARG2 
USER=unknown 
PATH=/tmp 

argv[0]: echoall 
argv[1]: only 1 arg 
A=1