summaryrefslogtreecommitdiff
path: root/sh.c
diff options
context:
space:
mode:
authorRobert Morris <[email protected]>2019-06-11 09:57:14 -0400
committerRobert Morris <[email protected]>2019-06-11 09:57:14 -0400
commit5753553213df8f9de851adb68377db43faecb91f (patch)
tree3b629ff54897fca414146677532cb459a2ed11ba /sh.c
parent91ba81110acd3163f7de3580b677eece0c57f5e7 (diff)
downloadxv6-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.c493
1 files changed, 0 insertions, 493 deletions
diff --git a/sh.c b/sh.c
deleted file mode 100644
index 054bab9..0000000
--- a/sh.c
+++ /dev/null
@@ -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;
-}