// 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. 第194天:js---函数对象详解(arguments、length)

    一.函数即对象 function add1(a,b){ return a+b; } //Function对象的实例 -- 高级技巧 --- 写框架必须用的... //前面表示参数,后面表示函数语句 v ...

  2. asp.netMVC中权限控制论

    这里设想了一个简单的思路,如果用户登录了,也就是session中有值才可以在控制器中操作,这样先添加一个控制器,如下代码: public class AuthController : Controll ...

  3. CSUOJ1329——一行盒子_湖南省第九届大学生计算机程序设计竞赛

    题目是中文的我就不是说明了,比赛的时候看过题目后队友说是splay来做,细想来省赛不会出这么坑的题目吧. 于是比赛还有一个小时左右把该做的都做完了以后,我们队三个人都来思考这个题目了.不过还好很快我们 ...

  4. css基于文件格式使用不同的样式

    a[href^="http://"]{ padding-right: 20px; background: url(external.gif) no-repeat center ri ...

  5. Python常忘的进阶知识(上)

    0.目录 1.面向对象 1.1 函数与方法 1.2 类变量与实例变量 1.3 实例方法.类方法.静态方法 1.4 公开和私有:没有什么是不能访问的 1.5 继承 2.正则表达式 2.1 Python内 ...

  6. 「美团 CodeM 资格赛」跳格子

    题目描述 nnn 个格子排成一列,一开始,你在第一个格子,目标为跳到第 n 个格子.在每个格子 i 里面你可以做出两个选择: 选择「a」:向前跳 ai​​ 步. 选择「b」:向前跳 bi 步. 把每步 ...

  7. 在洛谷3369 Treap模板题 中发现的Splay详解

    本题的Splay写法(无指针Splay超详细) 前言 首先来讲...终于调出来了55555...调了整整3天..... 看到大部分大佬都是用指针来实现的Splay.小的只是按照Splay的核心思想和原 ...

  8. 洛谷 P1865 A % B Problem

    题目戳 题目背景 题目名称是吸引你点进来的 实际上该题还是很水的 题目描述 区间质数个数 输入输出格式 输入格式: 一行两个整数 询问次数n,范围m 接下来n行,每行两个整数 l,r 表示区间 输出格 ...

  9. Django基于正则表达式的URL(1)

    1. 此时,用户只能看到列表,如果用户想查看详细信息,应该再增加程序. 2. 把信息用a标签包起来以后,详细信息就有了可以跳转的功能. . 3. 点击不同的用户名时,获取到不同的信息. 3.1 在ur ...

  10. 解题:ZJOI 2006 书架

    题面 学习了如何在维护序列的平衡树上查找某个数:按初始的顺序定个权值,然后每次找那个权值的DFS序即可.具体实现就是不停往上跳,然后是父亲的右儿子就加上父亲的左儿子,剩下的就是继续熟悉无旋树堆 #in ...