我正在编写一个 UNIX shell,我必须使用execv()
系统调用来创建一个进程。的参数之一execv()
是可执行文件的文件路径。因此,如果有人输入/bin/ls
,它将运行ls
可执行文件。但我需要的是一个函数,当ls
输入时,它将搜索ls
(如which
命令)的文件路径。有没有允许我这样做的功能?
不幸的是,这是一个学校项目,我不允许使用execvp()
。我需要实现一些路径搜索功能,然后将该文件路径添加到execv()
参数中。
用于PATH = getenv("PATH")
从环境中获取路径字符串,然后使用对strtok(PATH,":")
thenstrtok(NULL,":")
的连续调用将字符串中的路径解析PATH
为 的数组char **path
,您需要使用malloc()
. 将path[x]
++'/'
放入argv[0]
缓冲区,并用于access(buffer, X_OK)
查看是否可以在该路径位置执行文件,如果可以,请执行execv(buffer,argv)
.
您需要 execvp(),它将搜索 PATH 变量中指定的路径,除非文件名包含“/”。
使用execvp
.
char *args[] = {"ls", (char *) NULL};
execvp("ls", args);
例如,此示例将执行/bin/echo
(假设/bin
在您的 PATH 上)。
#include <unistd.h>
int main()
{
char *args[] = {"echo", "hello world", (char *) NULL};
execvp("echo", args);
return 0;
}
如果您不能使用 execvp,您可以char** environ
从 <unistd.h> 或char* getenv(const char* name)
<stdlib.h> 获取 PATH 变量,然后用于int access(const char* filename, int mode)
查看文件是否存在并且是否可执行。我将把实施留给你,因为这是一个学校项目。
我认为 execvp() 可以满足您的需要。
编辑:所以您实际上是在问如何手动执行此操作?在这种情况下...
或者,如果您想要一个真正可靠的实现,请使用this。不过,它可能会引发剽窃检测器:)
access()
一些人建议您stat()
在尝试使用execv()
. 你不需要这样做。execv()
如果无法执行请求的文件,将返回错误。
execvp
:-)
编辑:好的。这是一个 Perl 版本,它可以作为您的问题的伪代码。
use List::Util qw(first);
my @path = split /:/, $ENV{PATH};
my $dir = first {$_ ||= '.'; -x "$_/$name"} @path
or die "Can't find program $name\n";
exec "$dir/$name", @args;
split
使用给定的分隔符将字符串拆分为字符串数组。first
找到符合某个标准的第一个项目;在这里,目录和正在寻找的名称的连接是可执行的(-x
)。然后它运行。
希望能帮助到你!
从 execvp 手册页:
The functions execlp() and execvp() will duplicate the actions of the
shell in searching for an executable file if the specified filename
does not contain a slash (/) character. The search path is the path
specified in the environment by the PATH variable. If this variable
isn’t specified, the default path ‘‘:/bin:/usr/bin’’ is used. In addi-
tion, certain errors are treated specially.
也许您可以使用 execlp()?如果必须使用 execv,则需要获取 PATH 环境变量的值,使用 strtok() 解析它以获取各个路径,将文件名附加到每个路径并尝试使用 execv() 执行它。
我会提供代码,但我不会为你做作业。
哦,学校项目...
好吧,如果您想要“类似哪个”的东西,为什么不直接执行“哪个”本身(Linux 上的 /usr/bin/which,而不是 bash 别名或 tcsh 内置)来获取您正在寻找的路径...
:-)