zoukankan      html  css  js  c++  java
  • 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
    ", 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
    ", 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 
    
    165             if(chdir(buf+3) < 0)
    166                 printf(2, "cannot cd %s
    ", 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
    ", 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[] = " 	
    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
    ", 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 }
  • 相关阅读:
    蓝牙协议分析(11)_BLE安全机制之SM
    蓝牙协议分析(10)_BLE安全机制之LE Encryption
    蓝牙协议分析(9)_BLE安全机制之LL Privacy
    蓝牙协议分析(8)_BLE安全机制之白名单
    蓝牙协议分析(7)_BLE连接有关的技术分析
    蓝牙协议分析(6)_BLE地址类型
    蓝牙协议分析(5)_BLE广播通信相关的技术分析
    蓝牙协议分析(4)_IPv6 Over BLE介绍
    蓝牙协议分析(3)_BLE协议栈介绍
    ActiveMq
  • 原文地址:https://www.cnblogs.com/LinKArftc/p/5814402.html
Copyright © 2011-2022 走看看