使用execve的新路径来运行ls命令

jam*_*mes 3 c path exec execve

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

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

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

使用相同的args []我使用execvp并且ls工作并搜索我当前的路径.

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

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

Jon*_*ler 10

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

如果您使用/bin当前目录运行程序(因为./ls- 也ls就是存在),您将获得预期的结果(或多或少).

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

或继续使用execvp(),但将变量设置为environ新环境.请注意,environ现在(POSIX 2008)已声明<unistd.h>,但以前未在任何地方声明.

extern char **environ;

environ = env_args;
execvp(args[0], &args[0]);
Run Code Online (Sandbox Code Playgroud)

您不需要保存旧值并将其恢复; 你在子进程中并且切换它的环境不会影响主程序(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;
}
Run Code Online (Sandbox Code Playgroud)

我得到'糟糕!' 然后列出我的目录.当我ls在当前目录中创建可执行文件时:

#!/bin/sh
echo "Haha!"
Run Code Online (Sandbox Code Playgroud)

然后我没有得到'糟糕!' 并得到'哈哈!'.