// Shell.

 #include "types.h"
#include "user.h"
#include "fcntl.h" // Parsed command representation
#define EXEC 1
#define REDIR 2
#define PIPE 3
#define LIST 4
#define BACK 5 #define MAXARGS 10 struct cmd {
int type;
}; struct execcmd {
int type;
char *argv[MAXARGS];
char *eargv[MAXARGS];
}; struct redircmd {
int type;
struct cmd *cmd;
char *file;
char *efile;
int mode;
int fd;
}; struct pipecmd {
int type;
struct cmd *left;
struct cmd *right;
}; struct listcmd {
int type;
struct cmd *left;
struct cmd *right;
}; struct backcmd {
int type;
struct cmd *cmd;
};
int fork1(void); // Fork but panics on failure.
void panic(char*);
struct cmd *parsecmd(char*); // Execute cmd. Never returns.
void
runcmd(struct cmd *cmd)
{
int p[];
struct backcmd *bcmd;
struct execcmd *ecmd;
struct listcmd *lcmd;
struct pipecmd *pcmd;
struct redircmd *rcmd; if(cmd == )
exit(); switch(cmd->type){
default:
panic("runcmd"); case EXEC:
ecmd = (struct execcmd*)cmd;
if(ecmd->argv[] == )
exit();
exec(ecmd->argv[], ecmd->argv);
printf(, "exec %s failed\n", ecmd->argv[]);
break; case REDIR:
rcmd = (struct redircmd*)cmd;
close(rcmd->fd);
if(open(rcmd->file, rcmd->mode) < ){
printf(, "open %s failed\n", rcmd->file);
exit();
}
runcmd(rcmd->cmd);
break; case LIST:
lcmd = (struct listcmd*)cmd;
if(fork1() == )
runcmd(lcmd->left);
wait();
runcmd(lcmd->right);
break; case PIPE:
pcmd = (struct pipecmd*)cmd;
if(pipe(p) < )
panic("pipe");
if(fork1() == ){
close();
dup(p[]);
close(p[]);
close(p[]);
runcmd(pcmd->left);
}
if(fork1() == ){
close();
dup(p[]);
close(p[]);
close(p[]);
runcmd(pcmd->right);
}
close(p[]);
close(p[]);
wait();
wait();
break; case BACK:
bcmd = (struct backcmd*)cmd;
if(fork1() == )
runcmd(bcmd->cmd);
break;
}
exit();
} int
getcmd(char *buf, int nbuf)
{
printf(, "$ ");
memset(buf, , nbuf);
gets(buf, nbuf);
if(buf[] == ) // EOF
return -;
return ;
} int
main(void)
{
static char buf[];
int fd; // Assumes three file descriptors open.
while((fd = open("console", O_RDWR)) >= ){
if(fd >= ){
close(fd);
break;
}
} // Read and run input commands.
while(getcmd(buf, sizeof(buf)) >= ){
if(buf[] == ’c’ && buf[] == ’d’ && buf[] == ’ ’){
// Clumsy but will have to do for now.
// Chdir has no effect on the parent if run in the child.
buf[strlen(buf)-] = ; // chop \n
if(chdir(buf+) < )
printf(, "cannot cd %s\n", buf+);
continue;
}
if(fork1() == )
runcmd(parsecmd(buf));
wait();
}
exit();
} void
panic(char *s)
{
printf(, "%s\n", s);
exit();
} int
fork1(void)
{
int pid; pid = fork();
if(pid == -)
panic("fork");
return pid;
} // Constructors struct cmd*
execcmd(void)
{
struct execcmd *cmd; cmd = malloc(sizeof(*cmd));
memset(cmd, , sizeof(*cmd));
cmd->type = EXEC;
return (struct cmd*)cmd;
} struct cmd*
redircmd(struct cmd *subcmd, char *file, char *efile, int mode, int fd)
{
struct redircmd *cmd; cmd = malloc(sizeof(*cmd));
memset(cmd, , sizeof(*cmd));
cmd->type = REDIR;
cmd->cmd = subcmd;
cmd->file = file;
cmd->efile = efile;
cmd->mode = mode;
cmd->fd = fd;
return (struct cmd*)cmd;
} struct cmd*
pipecmd(struct cmd *left, struct cmd *right)
{
struct pipecmd *cmd; cmd = malloc(sizeof(*cmd));
memset(cmd, , sizeof(*cmd));
cmd->type = PIPE;
cmd->left = left;
cmd->right = right;
return (struct cmd*)cmd;
} struct cmd*
listcmd(struct cmd *left, struct cmd *right)
{
struct listcmd *cmd; cmd = malloc(sizeof(*cmd));
memset(cmd, , sizeof(*cmd));
cmd->type = LIST;
cmd->left = left;
cmd->right = right;
return (struct cmd*)cmd;
} struct cmd*
backcmd(struct cmd *subcmd)
{
struct backcmd *cmd; cmd = malloc(sizeof(*cmd));
memset(cmd, , sizeof(*cmd));
cmd->type = BACK;
cmd->cmd = subcmd;
return (struct cmd*)cmd;
} // Parsing char whitespace[] = " \t\r\n\v";
char symbols[] = "<|>&;()"; int
gettoken(char **ps, char *es, char **q, char **eq)
{
char *s;
int ret; s = *ps;
while(s < es && strchr(whitespace, *s))
s++;
if(q)
*q = s;
ret = *s;
switch(*s){
case :
break;
case ’|’:
case ’(’:
case ’)’:
case ’;’:
case ’&’:
case ’<’:
s++;
break;
case ’>’:
s++;
if(*s == ’>’){
ret = ’+’;
s++;
}
break;
default:
ret = ’a’;
while(s < es && !strchr(whitespace, *s) && !strchr(symbols, *s))
s++;
break;
}
if(eq)
*eq = s; while(s < es && strchr(whitespace, *s))
s++;
*ps = s;
return ret;
} int
peek(char **ps, char *es, char *toks)
{
char *s; s = *ps;
while(s < es && strchr(whitespace, *s))
s++;
*ps = s;
return *s && strchr(toks, *s);
} struct cmd *parseline(char**, char*);
struct cmd *parsepipe(char**, char*);
struct cmd *parseexec(char**, char*);
struct cmd *nulterminate(struct cmd*); struct cmd*
parsecmd(char *s)
{
char *es;
struct cmd *cmd; es = s + strlen(s);
cmd = parseline(&s, es);
peek(&s, es, "");
if(s != es){
printf(, "leftovers: %s\n", s);
panic("syntax");
}
nulterminate(cmd);
return cmd;
} struct cmd*
parseline(char **ps, char *es)
{
struct cmd *cmd; cmd = parsepipe(ps, es);
while(peek(ps, es, "&")){
gettoken(ps, es, , );
cmd = backcmd(cmd);
}
if(peek(ps, es, ";")){
gettoken(ps, es, , );
cmd = listcmd(cmd, parseline(ps, es));
}
return cmd;
} struct cmd*
parsepipe(char **ps, char *es)
{
struct cmd *cmd; cmd = parseexec(ps, es);
if(peek(ps, es, "|")){
gettoken(ps, es, , );
cmd = pipecmd(cmd, parsepipe(ps, es));
}
return cmd;
} struct cmd*
parseredirs(struct cmd *cmd, char **ps, char *es)
{
int tok;
char *q, *eq; while(peek(ps, es, "<>")){
tok = gettoken(ps, es, , );
if(gettoken(ps, es, &q, &eq) != ’a’)
panic("missing file for redirection");
switch(tok){
case ’<’:
cmd = redircmd(cmd, q, eq, O_RDONLY, );
break;
case ’>’:
cmd = redircmd(cmd, q, eq, O_WRONLY|O_CREATE, );
break;
case ’+’: // >>
cmd = redircmd(cmd, q, eq, O_WRONLY|O_CREATE, );
break;
}
}
return cmd;
} struct cmd*
parseblock(char **ps, char *es)
{
struct cmd *cmd; if(!peek(ps, es, "("))
panic("parseblock");
gettoken(ps, es, , );
cmd = parseline(ps, es);
if(!peek(ps, es, ")"))
panic("syntax - missing )");
gettoken(ps, es, , );
cmd = parseredirs(cmd, ps, es);
return cmd;
} struct cmd*
parseexec(char **ps, char *es)
{
char *q, *eq;
int tok, argc;
struct execcmd *cmd;
struct cmd *ret; if(peek(ps, es, "("))
return parseblock(ps, es); ret = execcmd();
cmd = (struct execcmd*)ret; argc = ;
ret = parseredirs(ret, ps, es);
while(!peek(ps, es, "|)&;")){
if((tok=gettoken(ps, es, &q, &eq)) == )
break;
if(tok != ’a’)
panic("syntax");
cmd->argv[argc] = q;
cmd->eargv[argc] = eq;
argc++;
if(argc >= MAXARGS)
panic("too many args");
ret = parseredirs(ret, ps, es);
}
cmd->argv[argc] = ;
cmd->eargv[argc] = ;
return ret;
} // NUL-terminate all the counted strings.
struct cmd*
nulterminate(struct cmd *cmd)
{
int i;
struct backcmd *bcmd;
struct execcmd *ecmd;
struct listcmd *lcmd;
struct pipecmd *pcmd;
struct redircmd *rcmd; if(cmd == )
return ; switch(cmd->type){
case EXEC:
ecmd = (struct execcmd*)cmd;
for(i=; ecmd->argv[i]; i++)
*ecmd->eargv[i] = ;
break; case REDIR:
rcmd = (struct redircmd*)cmd;
nulterminate(rcmd->cmd);
*rcmd->efile = ;
break; case PIPE:
pcmd = (struct pipecmd*)cmd;
nulterminate(pcmd->left);
nulterminate(pcmd->right);
break; case LIST:
lcmd = (struct listcmd*)cmd;
nulterminate(lcmd->left);
nulterminate(lcmd->right);
break; case BACK:
bcmd = (struct backcmd*)cmd;
nulterminate(bcmd->cmd);
break;
}
return cmd;
}

xv6/sh.c的更多相关文章

  1. xv6的作业翻译——作业1 - shell和系统调用

    Xv6的lecture LEC 1 Operating systems   L1: O/S overview L1:O/S概述   * 6.828 goals 6.828的目标   Understan ...

  2. xv6课本翻译之——第0章 操作系统接口

    Chapter 0 第0章 Operating system interfaces 操作系统接口 The job of an operating system is to share a comput ...

  3. XV6操作系统接口

    操作系统接口 操作系统的工作是(1)将计算机的资源在多个程序间共享,并且给程序提供一系列比硬件本身更有用的服务.(2)管理并抽象底层硬件,举例来说,一个文字处理软件(比如 word)不用去关心自己使用 ...

  4. XV6环境搭建及注意事项

    Ubuntu16.04SLT 64位 工具链 sudo apt-get install gcc-multilib libsdl1.2-dev, libtool-bin, libglib2.0-dev, ...

  5. xv6 操作系统的环境搭建

    xv6 是 MIT 设计的一个教学型操纵系统.xv6 可在 Intel X86 框架上运行,为了方便,建议将 xv6 运行在 QEMU 虚拟机器上,本人的实验环境是 ubuntu 18.04 . 1. ...

  6. MIT 6.S081 xv6调试不完全指北

    前言 今晚在实验室摸鱼做6.S081的Lab3 Allocator,并立下flag,改掉一个bug就拍死一只在身边飞的蚊子.在击杀8只蚊子拿到Legendary后仍然没能通过usertest,人已原地 ...

  7. xv6学习笔记(4) : 进程调度

    xv6学习笔记(4) : 进程 xv6所有程序都是单进程.单线程程序.要明白这个概念才好继续往下看 1. XV6中进程相关的数据结构 在XV6中,与进程有关的数据结构如下 // Per-process ...

  8. 数据库备份并分离日志表(按月)sh 脚本

    #!/bin/sh year=`date +%Y` month=`date +%m` day=`date +%d` hour=`date +%H` dir="/data/dbbackup/f ...

  9. xv6课本翻译之——附录A Pc的硬件

    Appendix A 附录A PC hardware Pc的硬件 This appendix describes personal computer (PC) hardware, the platfo ...

随机推荐

  1. hdu3507 Print Article(斜率优化入门)(pascal)

    Problem Description Zero has an old printer that doesn't work well sometimes. As it is antique, he s ...

  2. BZOJ3811 玛里苟斯(线性基+概率期望)

    k=1的话非常好做,每个有1的位都有一半可能性提供贡献.由组合数的一些性质非常容易证明. k=2的话,平方的式子展开可以发现要计算的是每一对位提供的贡献,于是需要计算每一对位被同时选中的概率.找出所有 ...

  3. 洛谷 P4114 Qtree1

    Qtree系列都跟树有着莫大的联系,这道题当然也不例外 我是题面 读完题,我们大概就知道了,这道题非常简单,可以说是模板题.树剖+线段树轻松解决 直接看代码吧 #include<algorith ...

  4. Doves and bombs UVA - 10765(统计割顶所连接的连通块的数量)

    题意:给定一个n个点的连通的无向图,一个点的“鸽子值”定义为将它从图中删去后连通块的个数. 求对应的点 和 每个点的“鸽子值” 用一个数组在判断割顶的那个地方 累加标记一下所连接的连通块的数量即可 初 ...

  5. WildFly8(JBoss)默认web服务器-------Undertow

    Java微服务框架之Undertow 一.Undertow简介: Undertow 是红帽公司(RedHat)的开源产品,是 WildFly8(JBoos) 默认的 Web 服务器. 官网API给出一 ...

  6. 【BZOJ2151】种树(贪心)

    [BZOJ2151]种树(贪心) 题面 BZOJ 题解 如果没有相邻不能选的限制,那么这就是一道傻逼题. 只需要用一个堆维护一下就好了. 现在加上了相邻点的限制,那么我们就对于当前位置加入一个撤销操作 ...

  7. windows提权基础大全

    Not many people talk about serious Windows privilege escalation which is a shame. I think the reason ...

  8. 在 Xamarin.Forms 实现页面全屏显示

    NavigationPage.SetHasNavigationBar(this, false); 或者 <ContentPage ... NavigationPage.HasNavigation ...

  9. 回顾static与final的作用

    static是java中非常重要的一个关键字,而且它的用法也很丰富,主要有四种用法: 用来修饰成员变量,将其变为类的成员,从而实现所有对象对于该成员的共享: 用来修饰成员方法,将其变为类方法,可以直接 ...

  10. echart图跟随屏幕自适应变化

    var myChart = echarts.init(document.getElementById('main'),'macarons');// var option = { //...一些配置 / ...