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 int
135 getcmd(char *buf, int nbuf)
136 {
137     printf(2, "$ ");
138     memset(buf, 0, nbuf);
139     gets(buf, nbuf);
140     if(buf[0] == 0) // EOF
141         return -1;
142     return 0;
143 }
144
145 int
146 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 \n
165             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 void
177 panic(char *s)
178 {
179     printf(2, "%s\n", s);
180     exit();
181 }
182
183 int
184 fork1(void)
185 {
186     int pid;
187
188     pid = fork();
189     if(pid == -1)
190         panic("fork");
191     return pid;
192 }
193
194 // Constructors
195
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 // Parsing
262
263 char whitespace[] = " \t\r\n\v";
264 char symbols[] = "<|>&;()";
265
266 int
267 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 int
312 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 }
时间: 2024-10-24 19:43:54

xv6/sh.c的相关文章

23.dubbo脚本之stop.sh

#!/bin/bash cd `dirname $0` BIN_DIR=`pwd` cd .. DEPLOY_DIR=`pwd` CONF_DIR=$DEPLOY_DIR/conf SERVER_NAME=`sed '/dubbo.application.name/!d;s/.*=//' conf/dubbo.properties | tr -d '\r'` if [ -z "$SERVER_NAME" ]; then     SERVER_NAME=`hostname` fi PID

24.dubbo脚本之server.sh

#!/bin/bash cd `dirname $0` if [ "$1" = "start" ]; then ./start.sh else if [ "$1" = "stop" ]; then ./stop.sh else if [ "$1" = "debug" ]; then ./start.sh debug else if [ "$1" = "res

25.dubbo脚本之restart.sh

#!/bin/bash cd `dirname $0` ./stop.sh ./start.sh

Oracle 11g RAC 二节点root.sh执行报错故障一例

OEL6.X IBM v3500存储多路径配置   http://koumm.blog.51cto.com/703525/1439760 2. 采用RHEL6.5 multipath多路径软件安装采用ASMLIB方式配置ASM共享磁盘成功,但是在第二节点执 行root.sh报如下错误提示,解决方式见3. Disk Group CRS creation failed with the following message:   ORA-15018: diskgroup cannot be creat

当root.sh与ORA-15031相遇

近日处理一个Oracle Grid infrastructure(GI)安装的问题,在执行root.sh过程中失败,并显示下面错误: Disk Group OCR creation failed with the following message: ORA-15018: diskgroup cannot be created ORA-15031: disk specification '/dev/vx/rdsk/dg_db01/lv_vote1' matches no disks    <<

debian和ubuntu的sh dash bash

Ubuntu和debian 的 shell 默认安装的是 dash,而不是 bash.运行以下命令查看 sh 的详细信息,确认 shell 对应的程序是哪个:$ls -al /bin/sh dash 比 bash 更轻,更快.但 bash 却更常用.如果一些命令.脚本等总不能正常执行,有可能是 dash 的原因.比如编译 Android 源代码的时候,如果使用 dash,则有可能编译出错,或者编译的系统不能启动. 通过以下方式可以使 shell 切换回 bash:$sudo dpkg-recon

使用sh库执行shell命令

python中执行shell命令 之前执行shell命令多是通过os.system(shell命令)的方式来执行,比较麻烦. 了解到sh是一个比subprocess好的库,能够执行shell命令 1.查看ip: [[email protected] myblog]# ifconfigeth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500inet 172.31.253.193 netmask 255.255.240.0 broadcas

sh, 批量执行Linux命令

step 1:创建一个sh批处理命令文件 # vim /etc/batch_ssh/install_redis.sh step 2:给当前用户,能够执行sh脚本权限# chmod install_redis.sh 777 step 3: 编写要批量执行的命令,read表示等待前端用户输入,sleep表示等待时间单位为 秒. echo '\n begin to install 01 plugin \n'; yum install cpp -y; echo '\n yum finish instal

linux执行sh报错:$’\r’: 未找到命令的解决

背景 执行.sh脚本时出现$'\r': 未找到命令, 原因 是因为命令直接从windows 复制过来导致的 解决 yum install dos2unix dos2unix **.sh 进行转换 再次执行即可