Unix路径搜索C函数
我正在编写UNIX shell,必须使用execv()系统调用来创建进程。
execv()的参数之一是可执行文件的文件路径。因此,如果有人输入/ bin / ls
,它将运行ls
可执行文件。但是我需要的是一个这样的函数,当键入ls
时,它将搜索ls
的文件路径(就像which
命令一样)。有功能允许我这样做吗?
不幸的是,这是一个学校项目,不允许我使用execvp()
。我需要实现一些路径搜索功能,然后将该文件路径添加到execv()
参数中。
解决方案
我认为execvp()可以满足需求。
编辑:所以我们实际上是在问如何手动执行此操作?在这种情况下...
- 在envp中找到PATH(main()的第三个参数)
- 将其拆分为单独的路径
- 使用stat()检查程序在每个程序中是否存在
- 执行我们发现的第一个
或者,如果我们想要一个真正可靠的实现,请使用它。它可能会触发窃检测器:)
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(),它将搜索PATH变量中指定的路径,除非文件名包含'/'。
在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()执行它。
我会提供代码,但我不会为我们做功课。
使用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,则可以从<unistd.h>的char ** environ
中获取PATH变量,或者从<stdlib.h>的char * getenv(const char * name)
中获取,然后使用`int访问权限(const char *文件名,int模式)以查看文件是否存在并且可执行。
由于这是一个学校项目,因此我将把实施工作留给我们。
使用PATH = getenv(" PATH")
从环境中获取路径字符串,然后依次调用strtok(PATH,":")
然后使用strtok(NULL,":")
解析出从" PATH"字符串到" char ** path"数组的路径,我们将需要使用" malloc()"进行分配。将path [x]
+/'
+argv [0]
放入缓冲区中,并使用access(buffer,X_OK)
来查看是否可以在该路径位置执行文件,如果可以,执行execv(buffer,argv)
。
哦,一个学校的项目...
好吧,如果我们想要"喜欢哪个"这样的东西,为什么不直接执行"哪个"本身(在Linux上是/ usr / bin / which,而不是bash别名或者内置的tcsh)来获取所需内容的路径...
:-)
一些人建议我们在尝试使用execv()执行程序之前先调用access()或者stat()。我们不需要这样做。如果无法执行请求的文件,则execv()将返回错误。