我正在ubuntu上编写一个UNIX minishell,我正在尝试添加内置命令。当它不是内置命令时我会fork,然后子进程执行它,但是对于内置命令,我只是在当前进程中执行它。
所以,我需要一种方法来查看文件是否存在(如果它们不是内置命令),但是execvp使用环境PATH变量来自动查找它们,所以我不知道如何手动事先检查。
那么,你们是否知道如何通过提供名称来测试一个参数,看它是否是一个内置命令?
谢谢你们。
答案 0 :(得分:3)
我已经测试了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
返回值的测试被撤消path
参数。我的示例使用了副本real_path
.
被识别为外部二进制文件答案 1 :(得分:1)
您可以通过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;
}
答案 2 :(得分:1)
您可以做的是您可以更改特定目录的路径,然后使用#include<dirent.h>
头文件及其readdir
和scandir
函数遍历目录或{{1结构以查看文件是否存在于目录中。
答案 3 :(得分:1)
为什么要在调用execvp
之前测试?这是错误的做法。只需致电execvp
,它就会告诉您程序是否不存在。