7 // Parsed command representation
52 int fork1(void); // Fork but panics on failure.
54 struct cmd
*parsecmd(char*);
56 // Execute cmd. Never returns.
58 runcmd(struct cmd
*cmd
)
65 struct redircmd
*rcmd
;
75 ecmd
= (struct execcmd
*)cmd
;
76 if(ecmd
->argv
[0] == 0)
78 exec(ecmd
->argv
[0], ecmd
->argv
);
79 printf(2, "exec %s failed\n", ecmd
->argv
[0]);
83 rcmd
= (struct redircmd
*)cmd
;
85 if(open(rcmd
->file
, rcmd
->mode
) < 0){
86 printf(2, "open %s failed\n", rcmd
->file
);
93 lcmd
= (struct listcmd
*)cmd
;
101 pcmd
= (struct pipecmd
*)cmd
;
125 bcmd
= (struct backcmd
*)cmd
;
134 getcmd(char *buf
, int nbuf
)
137 memset(buf
, 0, nbuf
);
139 if(buf
[0] == 0) // EOF
147 static char buf
[100];
150 // Assumes three file descriptors open.
151 while((fd
= open("console", O_RDWR
)) >= 0){
158 // Read and run input commands.
159 while(getcmd(buf
, sizeof(buf
)) >= 0){
160 if(buf
[0] == 'c' && buf
[1] == 'd' && buf
[2] == ' '){
161 // Clumsy but will have to do for now.
162 // Chdir has no effect on the parent if run in the child.
163 buf
[strlen(buf
)-1] = 0; // chop \n
165 printf(2, "cannot cd %s\n", buf
+3);
169 runcmd(parsecmd(buf
));
178 printf(2, "%s\n", s
);
200 cmd
= malloc(sizeof(*cmd
));
201 memset(cmd
, 0, sizeof(*cmd
));
203 return (struct cmd
*)cmd
;
207 redircmd(struct cmd
*subcmd
, char *file
, char *efile
, int mode
, int fd
)
209 struct redircmd
*cmd
;
211 cmd
= malloc(sizeof(*cmd
));
212 memset(cmd
, 0, sizeof(*cmd
));
219 return (struct cmd
*)cmd
;
223 pipecmd(struct cmd
*left
, struct cmd
*right
)
227 cmd
= malloc(sizeof(*cmd
));
228 memset(cmd
, 0, sizeof(*cmd
));
232 return (struct cmd
*)cmd
;
236 listcmd(struct cmd
*left
, struct cmd
*right
)
240 cmd
= malloc(sizeof(*cmd
));
241 memset(cmd
, 0, sizeof(*cmd
));
245 return (struct cmd
*)cmd
;
249 backcmd(struct cmd
*subcmd
)
253 cmd
= malloc(sizeof(*cmd
));
254 memset(cmd
, 0, sizeof(*cmd
));
257 return (struct cmd
*)cmd
;
261 char whitespace
[] = " \t\r\n\v";
262 char symbols
[] = "<|>&;()";
265 gettoken(char **ps
, char *es
, char **q
, char **eq
)
271 while(s
< es
&& strchr(whitespace
, *s
))
296 while(s
< es
&& !strchr(whitespace
, *s
) && !strchr(symbols
, *s
))
303 while(s
< es
&& strchr(whitespace
, *s
))
310 peek(char **ps
, char *es
, char *toks
)
315 while(s
< es
&& strchr(whitespace
, *s
))
318 return *s
&& strchr(toks
, *s
);
321 struct cmd
*parseline(char**, char*);
322 struct cmd
*parsepipe(char**, char*);
323 struct cmd
*parseexec(char**, char*);
324 struct cmd
*nulterminate(struct cmd
*);
333 cmd
= parseline(&s
, es
);
336 printf(2, "leftovers: %s\n", s
);
344 parseline(char **ps
, char *es
)
348 cmd
= parsepipe(ps
, es
);
349 while(peek(ps
, es
, "&")){
350 gettoken(ps
, es
, 0, 0);
353 if(peek(ps
, es
, ";")){
354 gettoken(ps
, es
, 0, 0);
355 cmd
= listcmd(cmd
, parseline(ps
, es
));
361 parsepipe(char **ps
, char *es
)
365 cmd
= parseexec(ps
, es
);
366 if(peek(ps
, es
, "|")){
367 gettoken(ps
, es
, 0, 0);
368 cmd
= pipecmd(cmd
, parsepipe(ps
, es
));
374 parseredirs(struct cmd
*cmd
, char **ps
, char *es
)
379 while(peek(ps
, es
, "<>")){
380 tok
= gettoken(ps
, es
, 0, 0);
381 if(gettoken(ps
, es
, &q
, &eq
) != 'a')
382 panic("missing file for redirection");
385 cmd
= redircmd(cmd
, q
, eq
, O_RDONLY
, 0);
388 cmd
= redircmd(cmd
, q
, eq
, O_WRONLY
|O_CREATE
, 1);
391 cmd
= redircmd(cmd
, q
, eq
, O_WRONLY
|O_CREATE
, 1);
399 parseblock(char **ps
, char *es
)
403 if(!peek(ps
, es
, "("))
405 gettoken(ps
, es
, 0, 0);
406 cmd
= parseline(ps
, es
);
407 if(!peek(ps
, es
, ")"))
408 panic("syntax - missing )");
409 gettoken(ps
, es
, 0, 0);
410 cmd
= parseredirs(cmd
, ps
, es
);
415 parseexec(char **ps
, char *es
)
422 if(peek(ps
, es
, "("))
423 return parseblock(ps
, es
);
426 cmd
= (struct execcmd
*)ret
;
429 ret
= parseredirs(ret
, ps
, es
);
430 while(!peek(ps
, es
, "|)&;")){
431 if((tok
=gettoken(ps
, es
, &q
, &eq
)) == 0)
436 cmd
->eargv
[argc
] = eq
;
439 panic("too many args");
440 ret
= parseredirs(ret
, ps
, es
);
443 cmd
->eargv
[argc
] = 0;
447 // NUL-terminate all the counted strings.
449 nulterminate(struct cmd
*cmd
)
452 struct backcmd
*bcmd
;
453 struct execcmd
*ecmd
;
454 struct listcmd
*lcmd
;
455 struct pipecmd
*pcmd
;
456 struct redircmd
*rcmd
;
463 ecmd
= (struct execcmd
*)cmd
;
464 for(i
=0; ecmd
->argv
[i
]; i
++)
469 rcmd
= (struct redircmd
*)cmd
;
470 nulterminate(rcmd
->cmd
);
475 pcmd
= (struct pipecmd
*)cmd
;
476 nulterminate(pcmd
->left
);
477 nulterminate(pcmd
->right
);
481 lcmd
= (struct listcmd
*)cmd
;
482 nulterminate(lcmd
->left
);
483 nulterminate(lcmd
->right
);
487 bcmd
= (struct backcmd
*)cmd
;
488 nulterminate(bcmd
->cmd
);