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
);
201 cmd
= malloc(sizeof(*cmd
));
202 memset(cmd
, 0, sizeof(*cmd
));
204 return (struct cmd
*)cmd
;
208 redircmd(struct cmd
*subcmd
, char *file
, char *efile
, int mode
, int fd
)
210 struct redircmd
*cmd
;
212 cmd
= malloc(sizeof(*cmd
));
213 memset(cmd
, 0, sizeof(*cmd
));
220 return (struct cmd
*)cmd
;
224 pipecmd(struct cmd
*left
, struct cmd
*right
)
228 cmd
= malloc(sizeof(*cmd
));
229 memset(cmd
, 0, sizeof(*cmd
));
233 return (struct cmd
*)cmd
;
237 listcmd(struct cmd
*left
, struct cmd
*right
)
241 cmd
= malloc(sizeof(*cmd
));
242 memset(cmd
, 0, sizeof(*cmd
));
246 return (struct cmd
*)cmd
;
250 backcmd(struct cmd
*subcmd
)
254 cmd
= malloc(sizeof(*cmd
));
255 memset(cmd
, 0, sizeof(*cmd
));
258 return (struct cmd
*)cmd
;
263 char whitespace
[] = " \t\r\n\v";
264 char symbols
[] = "<|>&;()";
267 gettoken(char **ps
, char *es
, char **q
, char **eq
)
273 while(s
< es
&& strchr(whitespace
, *s
))
298 while(s
< es
&& !strchr(whitespace
, *s
) && !strchr(symbols
, *s
))
305 while(s
< es
&& strchr(whitespace
, *s
))
312 peek(char **ps
, char *es
, char *toks
)
317 while(s
< es
&& strchr(whitespace
, *s
))
320 return *s
&& strchr(toks
, *s
);
323 struct cmd
*parseline(char**, char*);
324 struct cmd
*parsepipe(char**, char*);
325 struct cmd
*parseexec(char**, char*);
326 struct cmd
*nulterminate(struct cmd
*);
335 cmd
= parseline(&s
, es
);
338 printf(2, "leftovers: %s\n", s
);
346 parseline(char **ps
, char *es
)
350 cmd
= parsepipe(ps
, es
);
351 while(peek(ps
, es
, "&")){
352 gettoken(ps
, es
, 0, 0);
355 if(peek(ps
, es
, ";")){
356 gettoken(ps
, es
, 0, 0);
357 cmd
= listcmd(cmd
, parseline(ps
, es
));
363 parsepipe(char **ps
, char *es
)
367 cmd
= parseexec(ps
, es
);
368 if(peek(ps
, es
, "|")){
369 gettoken(ps
, es
, 0, 0);
370 cmd
= pipecmd(cmd
, parsepipe(ps
, es
));
376 parseredirs(struct cmd
*cmd
, char **ps
, char *es
)
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");
387 cmd
= redircmd(cmd
, q
, eq
, O_RDONLY
, 0);
390 cmd
= redircmd(cmd
, q
, eq
, O_WRONLY
|O_CREATE
, 1);
393 cmd
= redircmd(cmd
, q
, eq
, O_WRONLY
|O_CREATE
, 1);
401 parseblock(char **ps
, char *es
)
405 if(!peek(ps
, es
, "("))
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
);
417 parseexec(char **ps
, char *es
)
424 if(peek(ps
, es
, "("))
425 return parseblock(ps
, es
);
428 cmd
= (struct execcmd
*)ret
;
431 ret
= parseredirs(ret
, ps
, es
);
432 while(!peek(ps
, es
, "|)&;")){
433 if((tok
=gettoken(ps
, es
, &q
, &eq
)) == 0)
438 cmd
->eargv
[argc
] = eq
;
441 panic("too many args");
442 ret
= parseredirs(ret
, ps
, es
);
445 cmd
->eargv
[argc
] = 0;
449 // NUL-terminate all the counted strings.
451 nulterminate(struct cmd
*cmd
)
454 struct backcmd
*bcmd
;
455 struct execcmd
*ecmd
;
456 struct listcmd
*lcmd
;
457 struct pipecmd
*pcmd
;
458 struct redircmd
*rcmd
;
465 ecmd
= (struct execcmd
*)cmd
;
466 for(i
=0; ecmd
->argv
[i
]; i
++)
471 rcmd
= (struct redircmd
*)cmd
;
472 nulterminate(rcmd
->cmd
);
477 pcmd
= (struct pipecmd
*)cmd
;
478 nulterminate(pcmd
->left
);
479 nulterminate(pcmd
->right
);
483 lcmd
= (struct listcmd
*)cmd
;
484 nulterminate(lcmd
->left
);
485 nulterminate(lcmd
->right
);
489 bcmd
= (struct backcmd
*)cmd
;
490 nulterminate(bcmd
->cmd
);