$ ls
准备
1 | gcc sh.c |
产生a.out
文件,写一个脚本t.sh
,内容如下:
1 | ls > y |
执行命令:./a.out < t.sh
,得到如下结果:
1 | redir not implemented |
有一些函数尚未实现,所以会打印错误信息。
执行简单的命令
命令解析的代码文件已经提供了,我们要做的事情就是根据解析的命令,调用exec函数,从而执行特定的命令。这里需要对exec函数有一些了解,输入命令man 3 exec
查看execv相关的描述,函数原型为:
1 | #include<unistd.h> |
具体使用方法参考手册,总之我们只需要在runcmd对应的case ' '
处添加如下代码即可;
1 | case ' ': |
编译并执行sh.c
,输入命令ls
,会提示cmd not find!
,这是因为exec
会在当前文件夹下寻找可执行文件ls
,然而并找不到这个文件,所以我们要输入绝对路径/bin/ls
1 | 6.828$ /bin/ls |
改进:添加环境变量
从上面的程序中我们可以看到,必须在sh
中输入绝对路径,才能找到文件名,那么我们能不能设计环境变量机制,只需要输入命令就能找到特定的文件?
TODO:为sh添加环境变量
IO重定向
现在我们进行IO重定向,使我们的shell可以执行如下语句:
1 | echo "6.828 is cool" > x.txt |
即将IO重定向至一个文件。这里我们需要对文件进行操作,所以需要open
和close
操作;此外,为了将文件描述符进行重定向,我们还需要用到dup2
函数
函数原型
dup2
1 | #include <unistd.h> |
- open
1 | int open (const char* Path, int flags [, int mode ]); // flags表示了文件处理方式 |
代码
命令解析已经帮帮我们做好了,我们只需要做下面几件事:
- 以特定的
cmd->flags
打开文件 - 对文件进行重定向
- 关闭文件
- exec()
所以我们的代码如下:
1 | case '>': |
现在当我们执行下面语句是,就会将给定文件重定向至标准输入/输出
1 | 6.828$ /bin/echo "Helloworld" > result |
执行管道命令
在执行管道命令前,我们先要明确管道的机制