3

我正在尝试使用 execve 来运行 ls 命令。目前我正在使用以下参数运行它:

execve(args[0], args, env_args)
//args looks like {"ls", "-l", "-a", NULL}
//env_args looks like {"PATH=/bin", "USER=me", NULL}

我期望这样做是使用我的新 env_args 运行 ls 命令,这意味着它将在我的 PATH 中查找 ls。然而,这段代码实际上并没有做任何事情,当我运行代码时,它只是返回到我的命令提示符而没有输出。

使用相同的 args[] 我正在使用 execvp 和 ls 工作并搜索了我当前的路径。

你能告诉我我做错了什么吗?

我想做的是编写我自己的 shell 程序,我可以在其中创建和导出自己的环境,并让 exec 使用我在 char** 中定义的环境。本质上,我正在编写自己的函数来对 env_args 进行操作以添加和删除变量,当我调用 exec 时,我希望能够在 {"ls", "-l", NULL} 上调用 exec 并让它查看我的新环境名为 ls 的有效程序的路径变量。我希望这能更好地解释我正在做的事情。我不认为 extern environ var 在这种情况下对我有用。

4

1 回答 1

11

execve()函数不看PATH;为此,您需要execvp(). 您的程序无法执行ls,显然您没有报告在execve(). 请注意,exec*()函数族的成员仅在错误时返回。

/bin如果您将程序作为当前目录运行,您将获得您期望的结果(或多或少) (因为./ls- aka ls- 将会存在)。

execve()在使用适当的 PATH 设置找到可执行文件后,您需要在第一个参数中提供可执行文件的路径名。

或继续使用execvp(),但将变量设置environ为您的新环境。请注意,这environ在 POSIX 全局变量中是独一无二的,因为它没有在任何标头中声明。

extern char **environ;

environ = env_args;
execvp(args[0], &args[0]);

您不需要保存旧值并恢复它;您在子进程中并且切换其环境不会影响主程序(shell)。


这似乎像我预期的那样工作 - 并证明原始代码的行为符合我的预期。

#include <stdio.h>
#include <unistd.h>

extern char **environ;

int main(void)
{
    char *args[]     = { "ls", "-l", "-a", NULL };
    char *env_args[] = { "PATH=/bin", "USER=me", NULL };

    execve(args[0], args, env_args);
    fprintf(stderr, "Oops!\n");

    environ = env_args;
    execvp(args[0], &args[0]);
    fprintf(stderr, "Oops again!\n");

    return -1;
}

我得到一个“哎呀!” 其次是我的目录列表。ls当我在当前目录中创建可执行文件时:

#!/bin/sh
echo "Haha!"

然后我没有得到“哎呀!” 并得到'哈哈!'。

于 2011-10-03T02:25:20.637 回答