我正在 ubuntu 上编写一个 UNIX minishell,并尝试在此时添加内置命令。当它不是内置命令时,我 fork 然后子进程执行它,但是对于内置命令,我将在当前进程中执行它。
所以,我需要一种方法来查看文件是否存在(如果存在,这不是内置命令),但是 execvp 使用环境 PATH 变量自动查找它们,所以我不知道如何手动事先检查。
那么,你们知道我如何通过提供名称来测试参数以查看它是否是内置命令吗?
谢谢你们。
最佳答案
我测试了Tom的答案
它包含了一些问题。我在这里修复了它们并提供了一个测试程序。
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
int is_file(const char* path) {
struct stat buf;
stat(path, &buf);
return S_ISREG(buf.st_mode);
}
/*
* returns non-zero if the file is a file in the system path, and executable
*/
int is_executable_in_path(char *name)
{
char *path = getenv("PATH");
char *item = NULL;
int found = 0;
if (!path)
return 0;
path = strdup(path);
char real_path[4096]; // or PATH_MAX or something smarter
for (item = strtok(path, ":"); (!found) && item; item = strtok(NULL, ":"))
{
sprintf(real_path, "%s/%s", item, name);
// printf("Testing %s\n", real_path);
if ( is_file(real_path) && !(
access(real_path, F_OK)
|| access(real_path, X_OK))) // check if the file exists and is executable
{
found = 1;
}
}
free(path);
return found;
}
int main()
{
if (is_executable_in_path("."))
puts(". is executable");
if (is_executable_in_path("echo"))
puts("echo is executable");
}
注释
access
返回值的测试被反转- 第二个 strtok 调用有错误的分隔符
- strtok 更改了
path
参数。我的示例使用副本 - 没有任何东西可以保证连接的
real_path
中的正确路径分隔符 char> - 没有检查匹配的文件是否真的是一个文件(目录也可以是“可执行的”)。这会导致奇怪的事情,比如
.
被识别为外部二进制文件
关于C 在调用 execvp 之前测试文件是否存在,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12765010/