如何使用 c 程序确定用户是否输入了 linux 中存在的命令
How to use a c program to determine if the user entered a command that exists in linux
我正在做这个让用户输入 c 字符串的程序,然后我想创建一个函数来检查用户输入的字符串是否是 linux 命令。
前任。
用户:猫
输出:cat 是一个命令
用户:你好
输出:你好不是命令
等...
有人告诉我可以使用 execvp,但我不想执行命令只是为了弄清楚它是否存在,我只想确定它是否存在。
我认为可以利用 linux 的 whereis 命令来输出特定命令的位置,但是我不知道如何在 c 中实现它。
我还被告知 stat() 可以工作,但我不确定如何工作,因为它的 marcos 只针对目录和文件进行更改。 cat 文件之类的命令也是如此吗?如果是这样,当我做 运行 统计时:
stat( cmd, &buff );
我不需要cmd的路径吗?
总体而言,我如何确定用户是否使用 c 在 linux 中输入了有效命令并让解决方案相对有利?
stat 系统调用提供有关文件的信息,前提是您已提供文件名的完整路径。如果您想知道文件和类型以及是否是exe和Linux cmd,则需要从根目录搜索然后检查每个文件然后确定类型等。我建议您尝试理解 unix shell 是如何工作的,那么你就会理解你的问题的答案。 exec 系列系统调用执行程序,您需要 fork 然后在子系统中调用 exec,否则您的程序将执行新命令。
你写:
wouldn't I need the cmd's path
是的。对于没有路径的任何命令(cat 不是 /usr/bin/cat),您需要在伪代码中遍历 PATH 变量的所有元素:
for (path in PATH) {
cmdpath = concat(path, "/", cmd);
stat(cmdpath, &statbuff);
...
}
但是,在不厌其烦地复制 execvp
中的工作之后,您所做的只是为奇怪的计时 ("race") 错误创建一个位置,可能会引入安全漏洞.有关此主题的介绍,请参阅此维基百科文章:https://en.wikipedia.org/wiki/Time_of_check_to_time_of_use
所以解决方案通常是您不想使用的解决方案:
if (execvp(cmd, args) == -1) {
printf("well, that didn't go well, did it?\n");
}
想要 "look before you leap" 方法很自然,但 "try it and see" 方法通常更简单、更安全。
编辑
您对破坏文件的担心令人钦佩,但这正是 "real" shell:
中发生的事情
# date >victim
# cat victim
Fri Feb 12 09:23:56 CST 2016
# shjsds >victim
shjsds: Command not found.
# cat victim
# ! file was clobbered
您可以结合使用 Linux which
命令和 C 函数 popen
:
char testCmd[100];
char usrCmd[100];
strcpy(testCmd, "which ");
strcpy(usrCmd, "cat hello.txt");
strncat(testCmd, usrCmd, 93);
char path[100];
FILE *p = popen( testCmd , "r");
if(p ) {
while(fgets(path, sizeof(path), p) != NULL) {
printf("%s", path);
}
}
which
命令 returns 其参数的路径,传递 cat hello.txt
似乎也有效。如果你期望像输出重定向这样令人讨厌的事情,那么只将用户输入的第一个单词发送到 which
是有意义的。
which
打印命令的路径(如果它在路径中)或换行符(如果找不到命令)。
我正在做这个让用户输入 c 字符串的程序,然后我想创建一个函数来检查用户输入的字符串是否是 linux 命令。 前任。 用户:猫 输出:cat 是一个命令
用户:你好 输出:你好不是命令
等...
有人告诉我可以使用 execvp,但我不想执行命令只是为了弄清楚它是否存在,我只想确定它是否存在。
我认为可以利用 linux 的 whereis 命令来输出特定命令的位置,但是我不知道如何在 c 中实现它。
我还被告知 stat() 可以工作,但我不确定如何工作,因为它的 marcos 只针对目录和文件进行更改。 cat 文件之类的命令也是如此吗?如果是这样,当我做 运行 统计时:
stat( cmd, &buff );
我不需要cmd的路径吗?
总体而言,我如何确定用户是否使用 c 在 linux 中输入了有效命令并让解决方案相对有利?
stat 系统调用提供有关文件的信息,前提是您已提供文件名的完整路径。如果您想知道文件和类型以及是否是exe和Linux cmd,则需要从根目录搜索然后检查每个文件然后确定类型等。我建议您尝试理解 unix shell 是如何工作的,那么你就会理解你的问题的答案。 exec 系列系统调用执行程序,您需要 fork 然后在子系统中调用 exec,否则您的程序将执行新命令。
你写:
wouldn't I need the cmd's path
是的。对于没有路径的任何命令(cat 不是 /usr/bin/cat),您需要在伪代码中遍历 PATH 变量的所有元素:
for (path in PATH) {
cmdpath = concat(path, "/", cmd);
stat(cmdpath, &statbuff);
...
}
但是,在不厌其烦地复制 execvp
中的工作之后,您所做的只是为奇怪的计时 ("race") 错误创建一个位置,可能会引入安全漏洞.有关此主题的介绍,请参阅此维基百科文章:https://en.wikipedia.org/wiki/Time_of_check_to_time_of_use
所以解决方案通常是您不想使用的解决方案:
if (execvp(cmd, args) == -1) {
printf("well, that didn't go well, did it?\n");
}
想要 "look before you leap" 方法很自然,但 "try it and see" 方法通常更简单、更安全。
编辑
您对破坏文件的担心令人钦佩,但这正是 "real" shell:
中发生的事情# date >victim
# cat victim
Fri Feb 12 09:23:56 CST 2016
# shjsds >victim
shjsds: Command not found.
# cat victim
# ! file was clobbered
您可以结合使用 Linux which
命令和 C 函数 popen
:
char testCmd[100];
char usrCmd[100];
strcpy(testCmd, "which ");
strcpy(usrCmd, "cat hello.txt");
strncat(testCmd, usrCmd, 93);
char path[100];
FILE *p = popen( testCmd , "r");
if(p ) {
while(fgets(path, sizeof(path), p) != NULL) {
printf("%s", path);
}
}
which
命令 returns 其参数的路径,传递 cat hello.txt
似乎也有效。如果你期望像输出重定向这样令人讨厌的事情,那么只将用户输入的第一个单词发送到 which
是有意义的。
which
打印命令的路径(如果它在路径中)或换行符(如果找不到命令)。