// 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. LoadRunner脚本参数化常见错误

    错误代码:Error:missing newline in d:\loadrunner\username.dat 错误原因:场景设置不合理,参数数量不够,或者参数化文件有问题. 1)如果参数化文件反复 ...

  2. postman优缺点

    postman优缺点分析 优点:门槛低,上手快 优点: 脚本语言是js 优点:自带各种代码模块 优点:跨平台 优点: 免费版就已经非常强大了,支持http,https协议 优点:有命令行版本,newm ...

  3. linux下面Zookeeper的单机模式(standalone)

    1.下载 zk下载地址 http://mirrors.tuna.tsinghua.edu.cn/apache/zookeeper/ 我用的是http://mirrors.tuna.tsinghua.e ...

  4. [乱搞]hdu 6406 Taotao picks apples 笛卡尔树+倍增

    题目链接 Problem Description There is an apple tree in front of Taotao's house. When autumn comes, n app ...

  5. 【BZOJ1491】【NOI2007】社交网络(最短路,动态规划)

    [BZOJ1491][NOI2007]社交网络(最短路,动态规划) 题面 BZOJ 洛谷 图片是假的,只能到OJ上看 Description 在社交网络(socialnetwork)的研究中,我们常常 ...

  6. miya--图片上传--搭建分布式文件服务器(FastDFS+Nginx)

    资料获取(FastDFS+Nginx): 链接:https://pan.baidu.com/s/1kUI5WH5 密码:kzfd 安装rz,sz功能: yum install lrzsz 主攻: 利用 ...

  7. 2018-2019 ACM-ICPC 徐州区域赛 部分题解

    题目链接:2018-2019 ACM-ICPC, Asia Xuzhou Regional Contest A. Rikka with Minimum Spanning Trees 题意: 给出一个随 ...

  8. Qt ------ 我定义的规则 之 对象命名规则

    类型 + 特性,比如  button_closeLigth 非公有的变量前面要加上小写m_ (指的修饰符为private时) 静态变量前面加上小写s_ 其它变量以小写字母开头 静态变量全大写 (sta ...

  9. mobiscroll 案例git

    https://github.com/zhoushengmufc/iosselect

  10. go defer注意点,很容易出错的!!!

    1:defer是在return之前执行的  函数返回的过程是这样的:先给返回值赋值,然后调用defer表达式,最后才是返回到调用函数中 返回值 = xxx 调用defer函数 空的return fun ...