我正在尝试使用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对我有用。
答案 0 :(得分:10)
execve()
不看PATH;为此,您需要execvp()
。您的程序未能执行ls
,显然您没有报告在execve()
之后执行程序失败。请注意,exec*()
函数族的成员仅在出错时返回。
如果您使用/bin
作为当前目录运行程序(因为./ls
- 又名ls
- 将存在),您将得到预期的结果(或多或少)
在使用适当的PATH设置找到可执行文件后,需要在execve()
的第一个参数中提供可执行文件的路径名。
或继续使用execvp()
,但将变量environ
设置为新环境。请注意environ
现在(POSIX 2008)在<unistd.h>
中声明,但以前未在任何地方声明。
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!"
然后我没有得到'哎呀!'并得到'哈哈!'。