我在C中编写自己的shell。它需要能够显示用户当前目录,根据完整路径执行命令(必须使用execv ),并允许用户用cd更改目录。
这是作业。老师只给了我们关于C的基础入门,以及关于程序应该如何工作的非常简短的框架。因为我不是一个容易放弃的人,所以我一直在研究如何做这三天,但现在我很难过。
这是我到目前为止所做的:
我不确定如何从这里开始。我知道我必须使用execv命令,但在谷歌的研究中,我还没有找到一个我理解的例子。例如,如果命令是bin / ls,execv如何知道显示主目录中的所有文件/文件夹?如何告诉系统我更改了目录?
我一直在使用这个网站很多很有帮助:http://linuxgazette.net/111/ramankutty.html但是又一次,我很难过。
感谢您的帮助。如果我发布一些现有代码,请告诉我,但我不确定是否有必要。
答案 0 :(得分:1)
例如,如果命令是
bin/ls
,execv
如何知道显示主目录中的所有文件/文件夹?如何告诉系统我更改了目录?
每个进程都有一个当前工作目录,可以使用chdir
进行修改。子进程将从其父进程继承工作目录。因此,通常,您的shell将管理其当前工作目录以响应用户输入的cd
命令。当输入的命令不是内置命令时,您将fork
创建一个子进程,然后在那里调用execv
来执行二进制文件。
如果您考虑将PATH
考虑到不包含目录部分的程序名,那么您应该尝试PATH
元素和程序名称的所有可能组合。您可以检查指定的文件是否存在,或者只是尝试执行它,如果失败则继续执行下一个文件。如果所有execv
次呼叫都失败,则必须致电_exit
才能终止子进程。
请注意,大多数shell会将包含/
的任何命令视为直接传递给execv
的路径。如果路径 <{1}},则它是相对路径,操作系统将根据当前工作目录解析它。换句话说,示例中的/
将引用bin/ls
目录中的ls
二进制文件,该目录是当前工作目录的子目录。只有完全不包含bin
的命令才会被解释为内置命令(如/
)或cd
上的某个二进制文件的名称。
PATH
的第一个参数是计算它时的路径。 execv
列表的第一个元素传统上等于它被占用的名称,即没有添加argv
目录。在第一个参数之后,传递任何其他命令行参数,然后传递PATH
以终止列表。
答案 1 :(得分:1)
要实现cd命令,您只需要系统调用chdir
。
#include <unistd.h>
int chdir(
const char *path /* the path name */
);
所以你可以打电话给:
int ret1 = chdir("../foo/bar");
当可以更改到该目录时,chdir
的返回值为0,如果发生错误,则返回-1。对于错误,您应该合并手册页。
任何程序都可以检查当前目录,因此如果执行ls
而没有任何参数,那么ls会检查它正在运行的目录并使用此目录作为唯一参数。这是ls的一个功能,而不是execv
调用的功能。
第二部分。
#include <unistd.h>
int execv(
const char *path, /* programm path*/
char *const argv[]/* argument vector*/
);
execv
执行给定path
的可执行文件,并使用argv
中给出的参数。
因此,如果您想执行/bin/ls ../foo /bar
,则需要类似于
char *cmd_str = "/bin/ls";
char *argv[] = {cmd_str, "../foo", "/bar", NULL };
if (execv(cmd_str, argv) == -1 ){
/* an error occurred */
}
execv
返回的错误为-1。如果你想知道它为什么没有执行命令,请查看手册页。
NULL
中的char *argv[] = {cmd_str, "../foo", "/bar", NULL };
表示NULL
之后没有其他参数。
第三部分。 基于Unix的系统通常将带有/的命令视为可以直接执行的命令。这意味着您首先检查给定命令字符串中是否存在斜杠。
int ret_value;
if (strchr(cmd_str, '/')
if (execv(cmd_str, argv) == -1 ){
/* an error occurred */
}
如果没有斜杠,则需要遍历PATH
中的所有目录并检查是否可以执行该命令。因此,给定的命令为ls ../foo /bar
,并假设PATH
的值为".:/sbin:/bin:/usr/bin"
。
然后,我们会尝试首先执行./ls ../foo /bar
然后/usr/bin/ls ../foo /bar
,最后/bin/ls ../foo /bar
。
希望这有帮助。
答案 2 :(得分:1)
我认为问题是你认为shell负责ls
的工作。 ls
并不是shell的“部分”(至少在这种情况下)。 shell 执行一个名为ls
的程序。大多数评论似乎都在解释如何找到ls
,但我不相信这是你感到困惑的。
在编写shell之前,您应该仔细考虑shell的重点。这些评论间接指出了这样一个事实:shell“只是”必须“调用”ls
和chdir
之类的程序,而不是执行他们的任务。
答案 3 :(得分:1)
ls
自己知道,如果没有给出任何参数,它应该列出getcwd