在C中测试`foo`是否可以在命令行执行的最佳方法?

时间:2017-11-02 21:03:11

标签: c

在C中,找出命令行中是否有foo可在主机上执行的最佳方法是什么?如果我在bash命令行,我会运行type foo。在C中,我可以将type foo作为系统调用并检查退出状态。但是在可能的情况下避免系统调用是个好主意,对吗?还有更好的方法吗?

我的程序可能必须执行最终在shell脚本中运行foo的系统命令。 (这是别人的世界,他们应该使用foo。)但如果它在开始时可以告诉foo不可用,它可以避免做很多不必要的计算,因为没有foo意味着失败是肯定的。

1 个答案:

答案 0 :(得分:2)

type(及其表兄,which)是大多数类Unix操作系统提供的命令,也是大多数shell作为内在实现的命令。

您可以通过从程序中启动子进程来调用这些命令,然后读取它们的输出。如果要依赖shell命令版本的行为,则必须启动启动该shell的子进程,然后命令它运行typewhich。如果您不想使用子进程,那么您必须在程序中重新实现它们的逻辑。

使用the FreeBSD implementation of which作为指南,我们可以看到执行此操作的基本步骤:

  • 读取$PATH环境变量的值。
  • $PATH拆分为其包含的各种目录。
  • 测试目标文件/程序是否存在于路径中的各个子目录之一。

在代码中:

从env:

中读取$PATH
if ((p = getenv("PATH")) == NULL)
    exit(EXIT_FAILURE);

使用print_matches的一个参数调用which,提供$PATH的全部值:

while (argc > 0) {
    memcpy(path, p, pathlen);

    if (strlen(*argv) >= FILENAME_MAX ||
        print_matches(path, *argv) == -1)
        status = EXIT_FAILURE;
...

print_matches中,通过拆分$PATH字符来拆分:变量:

while ((d = strsep(&path, ":")) != NULL) {

对于每个目录,将目标程序连接到目录(检查以确保字符串不会变得太大):

if (snprintf(candidate, sizeof(candidate), "%s/%s", d,
        filename) >= (int)sizeof(candidate))
             continue;

然后测试以查看该文件是否存在:

if (is_there(candidate)) {