在C中,找出命令行中是否有foo
可在主机上执行的最佳方法是什么?如果我在bash命令行,我会运行type foo
。在C中,我可以将type foo
作为系统调用并检查退出状态。但是在可能的情况下避免系统调用是个好主意,对吗?还有更好的方法吗?
我的程序可能必须执行最终在shell脚本中运行foo
的系统命令。 (这是别人的世界,他们应该使用foo
。)但如果它在开始时可以告诉foo
不可用,它可以避免做很多不必要的计算,因为没有foo
意味着失败是肯定的。
答案 0 :(得分:2)
type
(及其表兄,which
)是大多数类Unix操作系统提供的命令,也是大多数shell作为内在实现的命令。
您可以通过从程序中启动子进程来调用这些命令,然后读取它们的输出。如果要依赖shell命令版本的行为,则必须启动启动该shell的子进程,然后命令它运行type
或which
。如果您不想使用子进程,那么您必须在程序中重新实现它们的逻辑。
使用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)) {