xv6/sh.c
// 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的更多相关文章
- xv6的作业翻译——作业1 - shell和系统调用
Xv6的lecture LEC 1 Operating systems L1: O/S overview L1:O/S概述 * 6.828 goals 6.828的目标 Understan ...
- xv6课本翻译之——第0章 操作系统接口
Chapter 0 第0章 Operating system interfaces 操作系统接口 The job of an operating system is to share a comput ...
- XV6操作系统接口
操作系统接口 操作系统的工作是(1)将计算机的资源在多个程序间共享,并且给程序提供一系列比硬件本身更有用的服务.(2)管理并抽象底层硬件,举例来说,一个文字处理软件(比如 word)不用去关心自己使用 ...
- XV6环境搭建及注意事项
Ubuntu16.04SLT 64位 工具链 sudo apt-get install gcc-multilib libsdl1.2-dev, libtool-bin, libglib2.0-dev, ...
- xv6 操作系统的环境搭建
xv6 是 MIT 设计的一个教学型操纵系统.xv6 可在 Intel X86 框架上运行,为了方便,建议将 xv6 运行在 QEMU 虚拟机器上,本人的实验环境是 ubuntu 18.04 . 1. ...
- MIT 6.S081 xv6调试不完全指北
前言 今晚在实验室摸鱼做6.S081的Lab3 Allocator,并立下flag,改掉一个bug就拍死一只在身边飞的蚊子.在击杀8只蚊子拿到Legendary后仍然没能通过usertest,人已原地 ...
- xv6学习笔记(4) : 进程调度
xv6学习笔记(4) : 进程 xv6所有程序都是单进程.单线程程序.要明白这个概念才好继续往下看 1. XV6中进程相关的数据结构 在XV6中,与进程有关的数据结构如下 // Per-process ...
- 数据库备份并分离日志表(按月)sh 脚本
#!/bin/sh year=`date +%Y` month=`date +%m` day=`date +%d` hour=`date +%H` dir="/data/dbbackup/f ...
- xv6课本翻译之——附录A Pc的硬件
Appendix A 附录A PC hardware Pc的硬件 This appendix describes personal computer (PC) hardware, the platfo ...
随机推荐
- hdu3507 Print Article(斜率优化入门)(pascal)
Problem Description Zero has an old printer that doesn't work well sometimes. As it is antique, he s ...
- BZOJ3811 玛里苟斯(线性基+概率期望)
k=1的话非常好做,每个有1的位都有一半可能性提供贡献.由组合数的一些性质非常容易证明. k=2的话,平方的式子展开可以发现要计算的是每一对位提供的贡献,于是需要计算每一对位被同时选中的概率.找出所有 ...
- 洛谷 P4114 Qtree1
Qtree系列都跟树有着莫大的联系,这道题当然也不例外 我是题面 读完题,我们大概就知道了,这道题非常简单,可以说是模板题.树剖+线段树轻松解决 直接看代码吧 #include<algorith ...
- Doves and bombs UVA - 10765(统计割顶所连接的连通块的数量)
题意:给定一个n个点的连通的无向图,一个点的“鸽子值”定义为将它从图中删去后连通块的个数. 求对应的点 和 每个点的“鸽子值” 用一个数组在判断割顶的那个地方 累加标记一下所连接的连通块的数量即可 初 ...
- WildFly8(JBoss)默认web服务器-------Undertow
Java微服务框架之Undertow 一.Undertow简介: Undertow 是红帽公司(RedHat)的开源产品,是 WildFly8(JBoos) 默认的 Web 服务器. 官网API给出一 ...
- 【BZOJ2151】种树(贪心)
[BZOJ2151]种树(贪心) 题面 BZOJ 题解 如果没有相邻不能选的限制,那么这就是一道傻逼题. 只需要用一个堆维护一下就好了. 现在加上了相邻点的限制,那么我们就对于当前位置加入一个撤销操作 ...
- windows提权基础大全
Not many people talk about serious Windows privilege escalation which is a shame. I think the reason ...
- 在 Xamarin.Forms 实现页面全屏显示
NavigationPage.SetHasNavigationBar(this, false); 或者 <ContentPage ... NavigationPage.HasNavigation ...
- 回顾static与final的作用
static是java中非常重要的一个关键字,而且它的用法也很丰富,主要有四种用法: 用来修饰成员变量,将其变为类的成员,从而实现所有对象对于该成员的共享: 用来修饰成员方法,将其变为类方法,可以直接 ...
- echart图跟随屏幕自适应变化
var myChart = echarts.init(document.getElementById('main'),'macarons');// var option = { //...一些配置 / ...