MIT6828-HW2-shell

$ ls

准备

阅读文献1第0章,完成作业2,下载sh.c,然后编译:

1
$ gcc sh.c

产生a.out文件,写一个脚本t.sh,内容如下:

1
2
3
4
5
6
ls > y
cat < y | sort | uniq | wc > y1
cat y1
rm y1
ls | sort | uniq | wc
rm y

执行命令:./a.out < t.sh,得到如下结果:

1
2
3
4
5
6
7
redir not implemented
exec not implemented
pipe not implemented
exec not implemented
exec not implemented
pipe not implemented
exec not implemented

有一些函数尚未实现,所以会打印错误信息。

执行简单的命令

命令解析的代码文件已经提供了,我们要做的事情就是根据解析的命令,调用exec函数,从而执行特定的命令。这里需要对exec函数有一些了解,输入命令man 3 exec查看execv相关的描述,函数原型为:

1
2
#include<unistd.h>
int execv(const char *path, char *constargv[]);

具体使用方法参考手册,总之我们只需要在runcmd对应的case ' '处添加如下代码即可;

1
2
3
4
5
6
7
8
case ' ':
ecmd = (struct execcmd*)cmd;
if(ecmd->argv[0] == 0)
_exit(0);
// Your code here ...
execv(ecmd->argv[0], ecmd->argv); //如果命令执行正确,exec会从另一个入口退出,因此后面的语句不应该被打印
fprintf(stderr, "cmd not find!\n");
break;

编译并执行sh.c,输入命令ls,会提示cmd not find!,这是因为exec会在当前文件夹下寻找可执行文件ls,然而并找不到这个文件,所以我们要输入绝对路径/bin/ls

1
2
6.828$ /bin/ls
a.out sh.c t.sh test_execv test_execv.c

改进:添加环境变量

从上面的程序中我们可以看到,必须在sh中输入绝对路径,才能找到文件名,那么我们能不能设计环境变量机制,只需要输入命令就能找到特定的文件?

TODO:为sh添加环境变量

IO重定向

现在我们进行IO重定向,使我们的shell可以执行如下语句:

1
2
echo "6.828 is cool" > x.txt
cat < x.txt

即将IO重定向至一个文件。这里我们需要对文件进行操作,所以需要openclose操作;此外,为了将文件描述符进行重定向,我们还需要用到dup2函数

函数原型

  • dup2
1
2
#include <unistd.h>
int dup2(int oldfd, int newfd); //将oldfd重定向到newfd
  • open
1
int open (const char* Path, int flags [, int mode ]);   // flags表示了文件处理方式

代码

命令解析已经帮帮我们做好了,我们只需要做下面几件事:

  • 以特定的cmd->flags打开文件
  • 对文件进行重定向
  • 关闭文件
  • exec()

所以我们的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
case '>':
case '<':
rcmd = (struct redircmd*)cmd;
// fprintf(stderr, "redir not implemented\n");
// Your code here ...
int fd = open(rcmd->file, rcmd->flags, 0666); //修改文件权限,否则打不开
if(fd < 0){
printf(2, "open %s failed\n", rcmd->file);
exit();
}
dup2(fd,rcmd->fd);
close(fd);
runcmd(rcmd->cmd);
break;

现在当我们执行下面语句是,就会将给定文件重定向至标准输入/输出

1
2
3
6.828$ /bin/echo "Helloworld" > result  
6.828$ /bin/cat < result
"Helloworld"

执行管道命令

在执行管道命令前,我们先要明确管道的机制

参考文献

0%