diff options
author | Robert Morris <[email protected]> | 2019-06-11 09:57:14 -0400 |
---|---|---|
committer | Robert Morris <[email protected]> | 2019-06-11 09:57:14 -0400 |
commit | 5753553213df8f9de851adb68377db43faecb91f (patch) | |
tree | 3b629ff54897fca414146677532cb459a2ed11ba /sh.c | |
parent | 91ba81110acd3163f7de3580b677eece0c57f5e7 (diff) | |
download | xv6-labs-5753553213df8f9de851adb68377db43faecb91f.tar.gz xv6-labs-5753553213df8f9de851adb68377db43faecb91f.tar.bz2 xv6-labs-5753553213df8f9de851adb68377db43faecb91f.zip |
separate source into kernel/ user/ mkfs/
Diffstat (limited to 'sh.c')
-rw-r--r-- | sh.c | 493 |
1 files changed, 0 insertions, 493 deletions
@@ -1,493 +0,0 @@ -// 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[2]; - struct backcmd *bcmd; - struct execcmd *ecmd; - struct listcmd *lcmd; - struct pipecmd *pcmd; - struct redircmd *rcmd; - - if(cmd == 0) - exit(); - - switch(cmd->type){ - default: - panic("runcmd"); - - case EXEC: - ecmd = (struct execcmd*)cmd; - if(ecmd->argv[0] == 0) - exit(); - exec(ecmd->argv[0], ecmd->argv); - printf(2, "exec %s failed\n", ecmd->argv[0]); - break; - - case REDIR: - rcmd = (struct redircmd*)cmd; - close(rcmd->fd); - if(open(rcmd->file, rcmd->mode) < 0){ - printf(2, "open %s failed\n", rcmd->file); - exit(); - } - runcmd(rcmd->cmd); - break; - - case LIST: - lcmd = (struct listcmd*)cmd; - if(fork1() == 0) - runcmd(lcmd->left); - wait(); - runcmd(lcmd->right); - break; - - case PIPE: - pcmd = (struct pipecmd*)cmd; - if(pipe(p) < 0) - panic("pipe"); - if(fork1() == 0){ - close(1); - dup(p[1]); - close(p[0]); - close(p[1]); - runcmd(pcmd->left); - } - if(fork1() == 0){ - close(0); - dup(p[0]); - close(p[0]); - close(p[1]); - runcmd(pcmd->right); - } - close(p[0]); - close(p[1]); - wait(); - wait(); - break; - - case BACK: - bcmd = (struct backcmd*)cmd; - if(fork1() == 0) - runcmd(bcmd->cmd); - break; - } - exit(); -} - -int -getcmd(char *buf, int nbuf) -{ - printf(2, "$ "); - memset(buf, 0, nbuf); - gets(buf, nbuf); - if(buf[0] == 0) // EOF - return -1; - return 0; -} - -int -main(void) -{ - static char buf[100]; - int fd; - - // Ensure that three file descriptors are open. - while((fd = open("console", O_RDWR)) >= 0){ - if(fd >= 3){ - close(fd); - break; - } - } - - // Read and run input commands. - while(getcmd(buf, sizeof(buf)) >= 0){ - if(buf[0] == 'c' && buf[1] == 'd' && buf[2] == ' '){ - // Chdir must be called by the parent, not the child. - buf[strlen(buf)-1] = 0; // chop \n - if(chdir(buf+3) < 0) - printf(2, "cannot cd %s\n", buf+3); - continue; - } - if(fork1() == 0) - runcmd(parsecmd(buf)); - wait(); - } - exit(); -} - -void -panic(char *s) -{ - printf(2, "%s\n", s); - exit(); -} - -int -fork1(void) -{ - int pid; - - pid = fork(); - if(pid == -1) - panic("fork"); - return pid; -} - -//PAGEBREAK! -// Constructors - -struct cmd* -execcmd(void) -{ - struct execcmd *cmd; - - cmd = malloc(sizeof(*cmd)); - memset(cmd, 0, 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, 0, 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, 0, 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, 0, 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, 0, sizeof(*cmd)); - cmd->type = BACK; - cmd->cmd = subcmd; - return (struct cmd*)cmd; -} -//PAGEBREAK! -// 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 0: - 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(2, "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, 0, 0); - cmd = backcmd(cmd); - } - if(peek(ps, es, ";")){ - gettoken(ps, es, 0, 0); - 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, 0, 0); - 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, 0, 0); - if(gettoken(ps, es, &q, &eq) != 'a') - panic("missing file for redirection"); - switch(tok){ - case '<': - cmd = redircmd(cmd, q, eq, O_RDONLY, 0); - break; - case '>': - cmd = redircmd(cmd, q, eq, O_WRONLY|O_CREATE, 1); - break; - case '+': // >> - cmd = redircmd(cmd, q, eq, O_WRONLY|O_CREATE, 1); - break; - } - } - return cmd; -} - -struct cmd* -parseblock(char **ps, char *es) -{ - struct cmd *cmd; - - if(!peek(ps, es, "(")) - panic("parseblock"); - gettoken(ps, es, 0, 0); - cmd = parseline(ps, es); - if(!peek(ps, es, ")")) - panic("syntax - missing )"); - gettoken(ps, es, 0, 0); - 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 = 0; - ret = parseredirs(ret, ps, es); - while(!peek(ps, es, "|)&;")){ - if((tok=gettoken(ps, es, &q, &eq)) == 0) - 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] = 0; - cmd->eargv[argc] = 0; - 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 == 0) - return 0; - - switch(cmd->type){ - case EXEC: - ecmd = (struct execcmd*)cmd; - for(i=0; ecmd->argv[i]; i++) - *ecmd->eargv[i] = 0; - break; - - case REDIR: - rcmd = (struct redircmd*)cmd; - nulterminate(rcmd->cmd); - *rcmd->efile = 0; - 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; -} |