我正在 ubuntu 上编写一个 UNIX minishell,并尝试在此时添加内置命令。当它不是内置命令时,我 fork 然后子执行它,但是对于内置命令,我将在当前进程中执行它。
因此,我需要一种方法来查看文件是否存在(如果存在,则不是内置命令),但是 execvp 使用环境 PATH 变量自动查找它们,所以我不知道如何事先手动检查。
那么,你们知道我如何通过提供名称来测试参数以查看它是否是内置命令吗?
多谢你们。
我已经测试了汤姆的答案
它包含许多问题。我在这里修复了它们并提供了一个测试程序。
#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
被颠倒了path
论点。我的示例使用副本real_path
.
被识别为外部二进制文件您可以遍历 PATH 目录,并且对于 PATH 中的每个条目(您必须将 PATH 与:
,可能使用strtok分开)在每个路径的末尾连接调用的命令的名称。创建此路径后,请检查文件是否存在以及是否可以使用access执行。
int is_built_in(char *path, char *name)
{
char *item = strtok(path, ":");
do {
char real_path[4096] = strcat(item, name); // you would normally alloc exactly the size needed but lets stick to it for the sake of the example
if (!access(real_path, F_OK) && !access(real_path, X_OK)) // check if the file exists and is executable
return 0;
} while ((item = strtok(NULL, ":")) != NULL);
return 1;
}
您可以做的是您可以更改特定目录的路径,然后使用#include<dirent.h>
头文件及其readdir
和scandir
函数遍历目录或stat
结构以查看该文件是否存在于目录中。
为什么要在调用之前execvp
进行测试?那是错误的做法。只要打电话execvp
,它会告诉你程序是否不存在。