Unix路径搜索C函数

时间:2020-03-06 14:51:21  来源:igfitidea点击:

我正在编写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()将返回错误。