首页 > 代码库 > xv6/sh.c
xv6/sh.c
1 // Shell. 2 3 #include "types.h" 4 #include "user.h" 5 #include "fcntl.h" 6 7 // Parsed command representation 8 #define EXEC 1 9 #define REDIR 2 10 #define PIPE 3 11 #define LIST 4 12 #define BACK 5 13 14 #define MAXARGS 10 15 16 struct cmd { 17 int type; 18 }; 19 20 struct execcmd { 21 int type; 22 char *argv[MAXARGS]; 23 char *eargv[MAXARGS]; 24 }; 25 26 struct redircmd { 27 int type; 28 struct cmd *cmd; 29 char *file; 30 char *efile; 31 int mode; 32 int fd; 33 }; 34 35 struct pipecmd { 36 int type; 37 struct cmd *left; 38 struct cmd *right; 39 }; 40 41 struct listcmd { 42 int type; 43 struct cmd *left; 44 struct cmd *right; 45 }; 46 47 struct backcmd { 48 int type; 49 struct cmd *cmd; 50 }; 51 int fork1(void); // Fork but panics on failure. 52 void panic(char*); 53 struct cmd *parsecmd(char*); 54 55 // Execute cmd. Never returns. 56 void 57 runcmd(struct cmd *cmd) 58 { 59 int p[2]; 60 struct backcmd *bcmd; 61 struct execcmd *ecmd; 62 struct listcmd *lcmd; 63 struct pipecmd *pcmd; 64 struct redircmd *rcmd; 65 66 if(cmd == 0) 67 exit(); 68 69 switch(cmd->type){ 70 default: 71 panic("runcmd"); 72 73 case EXEC: 74 ecmd = (struct execcmd*)cmd; 75 if(ecmd->argv[0] == 0) 76 exit(); 77 exec(ecmd->argv[0], ecmd->argv); 78 printf(2, "exec %s failed\n", ecmd->argv[0]); 79 break; 80 81 case REDIR: 82 rcmd = (struct redircmd*)cmd; 83 close(rcmd->fd); 84 if(open(rcmd->file, rcmd->mode) < 0){ 85 printf(2, "open %s failed\n", rcmd->file); 86 exit(); 87 } 88 runcmd(rcmd->cmd); 89 break; 90 91 case LIST: 92 lcmd = (struct listcmd*)cmd; 93 if(fork1() == 0) 94 runcmd(lcmd->left); 95 wait(); 96 runcmd(lcmd->right); 97 break; 98 99 100 101 case PIPE:102 pcmd = (struct pipecmd*)cmd;103 if(pipe(p) < 0)104 panic("pipe");105 if(fork1() == 0){106 close(1);107 dup(p[1]);108 close(p[0]);109 close(p[1]);110 runcmd(pcmd->left);111 }112 if(fork1() == 0){113 close(0);114 dup(p[0]);115 close(p[0]);116 close(p[1]);117 runcmd(pcmd->right);118 }119 close(p[0]);120 close(p[1]);121 wait();122 wait();123 break;124 125 case BACK:126 bcmd = (struct backcmd*)cmd;127 if(fork1() == 0)128 runcmd(bcmd->cmd);129 break;130 }131 exit();132 }133 134 int135 getcmd(char *buf, int nbuf)136 {137 printf(2, "$ ");138 memset(buf, 0, nbuf);139 gets(buf, nbuf);140 if(buf[0] == 0) // EOF141 return -1;142 return 0;143 }144 145 int146 main(void)147 {148 static char buf[100];149 int fd;150 151 // Assumes three file descriptors open.152 while((fd = open("console", O_RDWR)) >= 0){153 if(fd >= 3){154 close(fd);155 break;156 }157 }158 159 // Read and run input commands.160 while(getcmd(buf, sizeof(buf)) >= 0){161 if(buf[0] == ’c’ && buf[1] == ’d’ && buf[2] == ’ ’){162 // Clumsy but will have to do for now.163 // Chdir has no effect on the parent if run in the child.164 buf[strlen(buf)-1] = 0; // chop \n165 if(chdir(buf+3) < 0)166 printf(2, "cannot cd %s\n", buf+3);167 continue;168 }169 if(fork1() == 0)170 runcmd(parsecmd(buf));171 wait();172 }173 exit();174 }175 176 void177 panic(char *s)178 {179 printf(2, "%s\n", s);180 exit();181 }182 183 int184 fork1(void)185 {186 int pid;187 188 pid = fork();189 if(pid == -1)190 panic("fork");191 return pid;192 }193 194 // Constructors195 196 struct cmd*197 execcmd(void)198 {199 struct execcmd *cmd;200 201 cmd = malloc(sizeof(*cmd));202 memset(cmd, 0, sizeof(*cmd));203 cmd->type = EXEC;204 return (struct cmd*)cmd;205 }206 207 struct cmd*208 redircmd(struct cmd *subcmd, char *file, char *efile, int mode, int fd)209 {210 struct redircmd *cmd;211 212 cmd = malloc(sizeof(*cmd));213 memset(cmd, 0, sizeof(*cmd));214 cmd->type = REDIR;215 cmd->cmd = subcmd;216 cmd->file = file;217 cmd->efile = efile;218 cmd->mode = mode;219 cmd->fd = fd;220 return (struct cmd*)cmd;221 }222 223 struct cmd*224 pipecmd(struct cmd *left, struct cmd *right)225 {226 struct pipecmd *cmd;227 228 cmd = malloc(sizeof(*cmd));229 memset(cmd, 0, sizeof(*cmd));230 cmd->type = PIPE;231 cmd->left = left;232 cmd->right = right;233 return (struct cmd*)cmd;234 }235 236 struct cmd*237 listcmd(struct cmd *left, struct cmd *right)238 {239 struct listcmd *cmd;240 241 cmd = malloc(sizeof(*cmd));242 memset(cmd, 0, sizeof(*cmd));243 cmd->type = LIST;244 cmd->left = left;245 cmd->right = right;246 return (struct cmd*)cmd;247 }248 249 struct cmd*250 backcmd(struct cmd *subcmd)251 {252 struct backcmd *cmd;253 254 cmd = malloc(sizeof(*cmd));255 memset(cmd, 0, sizeof(*cmd));256 cmd->type = BACK;257 cmd->cmd = subcmd;258 return (struct cmd*)cmd;259 }260 261 // Parsing262 263 char whitespace[] = " \t\r\n\v";264 char symbols[] = "<|>&;()";265 266 int267 gettoken(char **ps, char *es, char **q, char **eq)268 {269 char *s;270 int ret;271 272 s = *ps;273 while(s < es && strchr(whitespace, *s))274 s++;275 if(q)276 *q = s;277 ret = *s;278 switch(*s){279 case 0:280 break;281 case ’|’:282 case ’(’:283 case ’)’:284 case ’;’:285 case ’&’:286 case ’<’:287 s++;288 break;289 case ’>’:290 s++;291 if(*s == ’>’){292 ret = ’+’;293 s++;294 }295 break;296 default:297 ret = ’a’;298 while(s < es && !strchr(whitespace, *s) && !strchr(symbols, *s))299 s++;300 break;301 }302 if(eq)303 *eq = s;304 305 while(s < es && strchr(whitespace, *s))306 s++;307 *ps = s;308 return ret;309 }310 311 int312 peek(char **ps, char *es, char *toks)313 {314 char *s;315 316 s = *ps;317 while(s < es && strchr(whitespace, *s))318 s++;319 *ps = s;320 return *s && strchr(toks, *s);321 }322 323 struct cmd *parseline(char**, char*);324 struct cmd *parsepipe(char**, char*);325 struct cmd *parseexec(char**, char*);326 struct cmd *nulterminate(struct cmd*);327 328 struct cmd*329 parsecmd(char *s)330 {331 char *es;332 struct cmd *cmd;333 334 es = s + strlen(s);335 cmd = parseline(&s, es);336 peek(&s, es, "");337 if(s != es){338 printf(2, "leftovers: %s\n", s);339 panic("syntax");340 }341 nulterminate(cmd);342 return cmd;343 }344 345 struct cmd*346 parseline(char **ps, char *es)347 {348 struct cmd *cmd;349 350 cmd = parsepipe(ps, es);351 while(peek(ps, es, "&")){352 gettoken(ps, es, 0, 0);353 cmd = backcmd(cmd);354 }355 if(peek(ps, es, ";")){356 gettoken(ps, es, 0, 0);357 cmd = listcmd(cmd, parseline(ps, es));358 }359 return cmd;360 }361 362 struct cmd*363 parsepipe(char **ps, char *es)364 {365 struct cmd *cmd;366 367 cmd = parseexec(ps, es);368 if(peek(ps, es, "|")){369 gettoken(ps, es, 0, 0);370 cmd = pipecmd(cmd, parsepipe(ps, es));371 }372 return cmd;373 }374 375 struct cmd*376 parseredirs(struct cmd *cmd, char **ps, char *es)377 {378 int tok;379 char *q, *eq;380 381 while(peek(ps, es, "<>")){382 tok = gettoken(ps, es, 0, 0);383 if(gettoken(ps, es, &q, &eq) != ’a’)384 panic("missing file for redirection");385 switch(tok){386 case ’<’:387 cmd = redircmd(cmd, q, eq, O_RDONLY, 0);388 break;389 case ’>’:390 cmd = redircmd(cmd, q, eq, O_WRONLY|O_CREATE, 1);391 break;392 case ’+’: // >>393 cmd = redircmd(cmd, q, eq, O_WRONLY|O_CREATE, 1);394 break;395 }396 }397 return cmd;398 }399 400 struct cmd*401 parseblock(char **ps, char *es)402 {403 struct cmd *cmd;404 405 if(!peek(ps, es, "("))406 panic("parseblock");407 gettoken(ps, es, 0, 0);408 cmd = parseline(ps, es);409 if(!peek(ps, es, ")"))410 panic("syntax - missing )");411 gettoken(ps, es, 0, 0);412 cmd = parseredirs(cmd, ps, es);413 return cmd;414 }415 416 struct cmd*417 parseexec(char **ps, char *es)418 {419 char *q, *eq;420 int tok, argc;421 struct execcmd *cmd;422 struct cmd *ret;423 424 if(peek(ps, es, "("))425 return parseblock(ps, es);426 427 ret = execcmd();428 cmd = (struct execcmd*)ret;429 430 argc = 0;431 ret = parseredirs(ret, ps, es);432 while(!peek(ps, es, "|)&;")){433 if((tok=gettoken(ps, es, &q, &eq)) == 0)434 break;435 if(tok != ’a’)436 panic("syntax");437 cmd->argv[argc] = q;438 cmd->eargv[argc] = eq;439 argc++;440 if(argc >= MAXARGS)441 panic("too many args");442 ret = parseredirs(ret, ps, es);443 }444 cmd->argv[argc] = 0;445 cmd->eargv[argc] = 0;446 return ret;447 }448 449 // NUL-terminate all the counted strings.450 struct cmd*451 nulterminate(struct cmd *cmd)452 {453 int i;454 struct backcmd *bcmd;455 struct execcmd *ecmd;456 struct listcmd *lcmd;457 struct pipecmd *pcmd;458 struct redircmd *rcmd;459 460 if(cmd == 0)461 return 0;462 463 switch(cmd->type){464 case EXEC:465 ecmd = (struct execcmd*)cmd;466 for(i=0; ecmd->argv[i]; i++)467 *ecmd->eargv[i] = 0;468 break;469 470 case REDIR:471 rcmd = (struct redircmd*)cmd;472 nulterminate(rcmd->cmd);473 *rcmd->efile = 0;474 break;475 476 case PIPE:477 pcmd = (struct pipecmd*)cmd;478 nulterminate(pcmd->left);479 nulterminate(pcmd->right);480 break;481 482 case LIST:483 lcmd = (struct listcmd*)cmd;484 nulterminate(lcmd->left);485 nulterminate(lcmd->right);486 break;487 488 case BACK:489 bcmd = (struct backcmd*)cmd;490 nulterminate(bcmd->cmd);491 break;492 }493 return cmd;494 }
xv6/sh.c
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。