我的任务是用C语言编写一个非常简单的shell。我没有给出太多的源代码,而且我才刚刚开始学习C语言,我只使用了scanf()
和printf()
并编写了简单函数。我只知道应该用fork()
和不同的exec()
编写。我花了很多时间分析其他外壳,但我不了解程序的结构和某些功能,例如:
help()
或date()
)进行比较并执行它们。fgets()
,然后使用strcmp()
?execvp()
如何知道用户输入是main
中的命令(功能)还是程序文件夹中的程序?答案 0 :(得分:2)
首先,让我说,对于一个刚学习C的人来说,这听起来像是一项艰巨的任务,除非它受到非常严格的限制。您需要分析其他外壳没有任何意义。我建议您与助教讨论作业的范围,以及根据您的经验应该做的事情。
不过,要回答您的问题:
为什么我们需要解析?
(在这种情况下)解析是采用一个字符序列并产生一个数据结构,程序可以对其进行处理。现在,如果不应该有任何参数,每行没有多个命令等,这可能是一个相当简单的结构。但是,您至少必须确保用户确实没有使用过参数,而不是写下无效的命令行,并关闭其右括号,等等。
如果我知道我不会在命令中使用参数
该程序不是为可以预测其行为的完美用户编写的。您必须容纳任何可以插入几乎所有内容的用户;您需要注意这种情况并报告错误。
读取用户输入。使用
fgets()
,然后使用strcmp()
?
请记住,fgets()
可能无法遍及整行-如果该行的长度大于缓冲区长度减去1。但是,也许可以保证行长度限制吗?还是被允许在超长线路上失败?
此外,在某些情况下,可能允许用户使用多余的空白作为行的一部分,在这种情况下,strcmp()
可能不会给您想要的内容。
执行,它如何工作? execvp()如何知道用户输入是我的主程序还是程序文件夹中的程序中的命令(函数)?
看看execvp()
的{{3}}(和朋友)。基本上,调用execvp()
时发生的事情是运行指定位置的二进制文件,而其命令行就是您作为execvp()
的第二个参数传递的。假设您运行
execvp("/path/to/foo", "/path/to/foo", "bar");
因此,运行/path/to/foo
上的程序。像任何程序一样,其argv[0]
是其自身的路径。其argc
将是2
,其argv[1]
将是"bar"
。它的工作目录(以及用户和组ID)将是运行execvp()
的进程的当前目录以及用户和组ID,因此-不一定是/path/to/foo
。
继续前面的示例,您可以执行以下操作:
chdir("/path/to");
execvp("foo", "foo", "bar");
此时foo
将以argv[0]
为foo
运行。