1219b2ee8SDavid du Colombier /* sh - simple shell - great for early stages of porting */
23e12c5d1SDavid du Colombier #include "u.h"
33e12c5d1SDavid du Colombier #include "libc.h"
43e12c5d1SDavid du Colombier
53e12c5d1SDavid du Colombier #define MAXLINE 200 /* maximum line length */
63e12c5d1SDavid du Colombier #define WORD 256 /* token code for words */
73e12c5d1SDavid du Colombier #define EOF -1 /* token code for end of file */
83e12c5d1SDavid du Colombier #define ispunct(c) (c=='|' || c=='&' || c==';' || c=='<' || \
93e12c5d1SDavid du Colombier c=='>' || c=='(' || c==')' || c=='\n')
103e12c5d1SDavid du Colombier #define isspace(c) (c==' ' || c=='\t')
11*dc5a79c1SDavid du Colombier #define execute(np) (ignored = (np? (*(np)->op)(np) : 0))
123e12c5d1SDavid du Colombier
133e12c5d1SDavid du Colombier typedef struct Node Node;
143e12c5d1SDavid du Colombier struct Node{ /* parse tree node */
153e12c5d1SDavid du Colombier int (*op)(Node *); /* operator function */
163e12c5d1SDavid du Colombier Node *args[2]; /* argument nodes */
173e12c5d1SDavid du Colombier char *argv[100]; /* argument pointers */
183e12c5d1SDavid du Colombier char *io[3]; /* i/o redirection */
193e12c5d1SDavid du Colombier };
203e12c5d1SDavid du Colombier
213e12c5d1SDavid du Colombier Node nodes[25]; /* node pool */
223e12c5d1SDavid du Colombier Node *nfree; /* next available node */
233e12c5d1SDavid du Colombier char strspace[10*MAXLINE]; /* string storage */
243e12c5d1SDavid du Colombier char *sfree; /* next free character in strspace */
253e12c5d1SDavid du Colombier int t; /* current token code */
263e12c5d1SDavid du Colombier char *token; /* current token text (in strspace) */
273e12c5d1SDavid du Colombier int putback = 0; /* lookahead */
28*dc5a79c1SDavid du Colombier char status[256]; /* exit status of most recent command */
293e12c5d1SDavid du Colombier int cflag = 0; /* command is argument to sh */
303e12c5d1SDavid du Colombier int tflag = 0; /* read only one line */
313e12c5d1SDavid du Colombier int interactive = 0; /* prompt */
323e12c5d1SDavid du Colombier char *cflagp; /* command line for cflag */
333e12c5d1SDavid du Colombier char *path[] ={"/bin", 0};
34*dc5a79c1SDavid du Colombier int ignored;
353e12c5d1SDavid du Colombier
363e12c5d1SDavid du Colombier Node *alloc(int (*op)(Node *));
373e12c5d1SDavid du Colombier int builtin(Node *np);
383e12c5d1SDavid du Colombier Node *command(void);
393e12c5d1SDavid du Colombier int getch(void);
403e12c5d1SDavid du Colombier int gettoken(void);
413e12c5d1SDavid du Colombier Node *list(void);
423e12c5d1SDavid du Colombier void error(char *s, char *t);
433e12c5d1SDavid du Colombier Node *pipeline(void);
443e12c5d1SDavid du Colombier void redirect(Node *np);
453e12c5d1SDavid du Colombier int setio(Node *np);
463e12c5d1SDavid du Colombier Node *simple(void);
473e12c5d1SDavid du Colombier int xpipeline(Node *np);
483e12c5d1SDavid du Colombier int xsimple(Node *np);
493e12c5d1SDavid du Colombier int xsubshell(Node *np);
503e12c5d1SDavid du Colombier int xnowait(Node *np);
513e12c5d1SDavid du Colombier int xwait(Node *np);
523e12c5d1SDavid du Colombier
53*dc5a79c1SDavid du Colombier void
main(int argc,char * argv[])543e12c5d1SDavid du Colombier main(int argc, char *argv[])
553e12c5d1SDavid du Colombier {
563e12c5d1SDavid du Colombier Node *np;
573e12c5d1SDavid du Colombier
583e12c5d1SDavid du Colombier if(argc>1 && strcmp(argv[1], "-t")==0)
593e12c5d1SDavid du Colombier tflag++;
603e12c5d1SDavid du Colombier else if(argc>2 && strcmp(argv[1], "-c")==0){
613e12c5d1SDavid du Colombier cflag++;
623e12c5d1SDavid du Colombier cflagp = argv[2];
633e12c5d1SDavid du Colombier }else if(argc>1){
643e12c5d1SDavid du Colombier close(0);
653e12c5d1SDavid du Colombier if(open(argv[1], 0) != 0){
663e12c5d1SDavid du Colombier error(": can't open", argv[1]);
673e12c5d1SDavid du Colombier exits("argument");
683e12c5d1SDavid du Colombier }
693e12c5d1SDavid du Colombier }else
703e12c5d1SDavid du Colombier interactive = 1;
713e12c5d1SDavid du Colombier for(;;){
723e12c5d1SDavid du Colombier if(interactive)
733e12c5d1SDavid du Colombier fprint(2, "%d$ ", getpid());
743e12c5d1SDavid du Colombier nfree = nodes;
753e12c5d1SDavid du Colombier sfree = strspace;
763e12c5d1SDavid du Colombier if((t=gettoken()) == EOF)
773e12c5d1SDavid du Colombier break;
783e12c5d1SDavid du Colombier if(t != '\n')
793e12c5d1SDavid du Colombier if(np = list())
803e12c5d1SDavid du Colombier execute(np);
813e12c5d1SDavid du Colombier else
823e12c5d1SDavid du Colombier error("syntax error", "");
833e12c5d1SDavid du Colombier while(t!=EOF && t!='\n') /* flush syntax errors */
843e12c5d1SDavid du Colombier t = gettoken();
853e12c5d1SDavid du Colombier }
86*dc5a79c1SDavid du Colombier exits(status);
873e12c5d1SDavid du Colombier }
883e12c5d1SDavid du Colombier
893e12c5d1SDavid du Colombier /* alloc - allocate for op and return a node */
903e12c5d1SDavid du Colombier Node*
alloc(int (* op)(Node *))913e12c5d1SDavid du Colombier alloc(int (*op)(Node *))
923e12c5d1SDavid du Colombier {
933e12c5d1SDavid du Colombier if(nfree < nodes+sizeof(nodes)){
943e12c5d1SDavid du Colombier nfree->op = op;
953e12c5d1SDavid du Colombier nfree->args[0] = nfree->args[1] = 0;
963e12c5d1SDavid du Colombier nfree->argv[0] = nfree->argv[1] = 0;
973e12c5d1SDavid du Colombier nfree->io[0] = nfree->io[1] = nfree->io[2] = 0;
983e12c5d1SDavid du Colombier return nfree++;
993e12c5d1SDavid du Colombier }
1003e12c5d1SDavid du Colombier error("node storage overflow", "");
1013e12c5d1SDavid du Colombier exits("node storage overflow");
102*dc5a79c1SDavid du Colombier return nil;
1033e12c5d1SDavid du Colombier }
1043e12c5d1SDavid du Colombier
1053e12c5d1SDavid du Colombier /* builtin - check np for builtin command and, if found, execute it */
1063e12c5d1SDavid du Colombier int
builtin(Node * np)1073e12c5d1SDavid du Colombier builtin(Node *np)
1083e12c5d1SDavid du Colombier {
1093e12c5d1SDavid du Colombier int n = 0;
110*dc5a79c1SDavid du Colombier char name[MAXLINE];
111*dc5a79c1SDavid du Colombier Waitmsg *wmsg;
1123e12c5d1SDavid du Colombier
1133e12c5d1SDavid du Colombier if(np->argv[1])
1143e12c5d1SDavid du Colombier n = strtoul(np->argv[1], 0, 0);
1153e12c5d1SDavid du Colombier if(strcmp(np->argv[0], "cd") == 0){
1163e12c5d1SDavid du Colombier if(chdir(np->argv[1]? np->argv[1] : "/") == -1)
1173e12c5d1SDavid du Colombier error(": bad directory", np->argv[0]);
1183e12c5d1SDavid du Colombier return 1;
1193e12c5d1SDavid du Colombier }else if(strcmp(np->argv[0], "exit") == 0)
120*dc5a79c1SDavid du Colombier exits(np->argv[1]? np->argv[1] : status);
1213e12c5d1SDavid du Colombier else if(strcmp(np->argv[0], "bind") == 0){
1223e12c5d1SDavid du Colombier if(np->argv[1]==0 || np->argv[2]==0)
1233e12c5d1SDavid du Colombier error("usage: bind new old", "");
1243e12c5d1SDavid du Colombier else if(bind(np->argv[1], np->argv[2], 0)==-1)
1253e12c5d1SDavid du Colombier error("bind failed", "");
1263e12c5d1SDavid du Colombier return 1;
1273e12c5d1SDavid du Colombier #ifdef asdf
1283e12c5d1SDavid du Colombier }else if(strcmp(np->argv[0], "unmount") == 0){
1293e12c5d1SDavid du Colombier if(np->argv[1] == 0)
1303e12c5d1SDavid du Colombier error("usage: unmount [new] old", "");
1313e12c5d1SDavid du Colombier else if(np->argv[2] == 0){
1323e12c5d1SDavid du Colombier if(unmount((char *)0, np->argv[1]) == -1)
1333e12c5d1SDavid du Colombier error("unmount:", "");
1343e12c5d1SDavid du Colombier }else if(unmount(np->argv[1], np->argv[2]) == -1)
1353e12c5d1SDavid du Colombier error("unmount", "");
1363e12c5d1SDavid du Colombier return 1;
1373e12c5d1SDavid du Colombier #endif
1383e12c5d1SDavid du Colombier }else if(strcmp(np->argv[0], "wait") == 0){
139*dc5a79c1SDavid du Colombier while((wmsg = wait()) != nil){
140*dc5a79c1SDavid du Colombier strncpy(status, wmsg->msg, sizeof(status)-1);
141*dc5a79c1SDavid du Colombier if(n && wmsg->pid==n){
1423e12c5d1SDavid du Colombier n = 0;
143*dc5a79c1SDavid du Colombier free(wmsg);
1443e12c5d1SDavid du Colombier break;
1453e12c5d1SDavid du Colombier }
146*dc5a79c1SDavid du Colombier free(wmsg);
147*dc5a79c1SDavid du Colombier }
1483e12c5d1SDavid du Colombier if(n)
1493e12c5d1SDavid du Colombier error("wait error", "");
1503e12c5d1SDavid du Colombier return 1;
151*dc5a79c1SDavid du Colombier }else if(strcmp(np->argv[0], "rfork") == 0){
152*dc5a79c1SDavid du Colombier char *p;
153*dc5a79c1SDavid du Colombier int mask;
154*dc5a79c1SDavid du Colombier
155*dc5a79c1SDavid du Colombier p = np->argv[1];
156*dc5a79c1SDavid du Colombier if(p == 0 || *p == 0)
157*dc5a79c1SDavid du Colombier p = "ens";
158*dc5a79c1SDavid du Colombier mask = 0;
159*dc5a79c1SDavid du Colombier
160*dc5a79c1SDavid du Colombier while(*p)
161*dc5a79c1SDavid du Colombier switch(*p++){
162*dc5a79c1SDavid du Colombier case 'n': mask |= RFNAMEG; break;
163*dc5a79c1SDavid du Colombier case 'N': mask |= RFCNAMEG; break;
164*dc5a79c1SDavid du Colombier case 'e': mask |= RFENVG; break;
165*dc5a79c1SDavid du Colombier case 'E': mask |= RFCENVG; break;
166*dc5a79c1SDavid du Colombier case 's': mask |= RFNOTEG; break;
167*dc5a79c1SDavid du Colombier case 'f': mask |= RFFDG; break;
168*dc5a79c1SDavid du Colombier case 'F': mask |= RFCFDG; break;
169*dc5a79c1SDavid du Colombier case 'm': mask |= RFNOMNT; break;
170*dc5a79c1SDavid du Colombier default: error(np->argv[1], "bad rfork flag");
171*dc5a79c1SDavid du Colombier }
172*dc5a79c1SDavid du Colombier rfork(mask);
173*dc5a79c1SDavid du Colombier
1743e12c5d1SDavid du Colombier return 1;
1753e12c5d1SDavid du Colombier }else if(strcmp(np->argv[0], "exec") == 0){
1763e12c5d1SDavid du Colombier redirect(np);
1773e12c5d1SDavid du Colombier if(np->argv[1] == (char *) 0)
1783e12c5d1SDavid du Colombier return 1;
1793e12c5d1SDavid du Colombier exec(np->argv[1], &np->argv[1]);
1803e12c5d1SDavid du Colombier n = np->argv[1][0];
1813e12c5d1SDavid du Colombier if(n!='/' && n!='#' && (n!='.' || np->argv[1][1]!='/'))
1823e12c5d1SDavid du Colombier for(n = 0; path[n]; n++){
1833e12c5d1SDavid du Colombier sprint(name, "%s/%s", path[n], np->argv[1]);
1843e12c5d1SDavid du Colombier exec(name, &np->argv[1]);
1853e12c5d1SDavid du Colombier }
1863e12c5d1SDavid du Colombier error(": not found", np->argv[1]);
1873e12c5d1SDavid du Colombier return 1;
1883e12c5d1SDavid du Colombier }
1893e12c5d1SDavid du Colombier return 0;
1903e12c5d1SDavid du Colombier }
1913e12c5d1SDavid du Colombier
1923e12c5d1SDavid du Colombier /* command - ( list ) [ ( < | > | >> ) word ]* | simple */
1933e12c5d1SDavid du Colombier Node*
command(void)1943e12c5d1SDavid du Colombier command(void)
1953e12c5d1SDavid du Colombier {
1963e12c5d1SDavid du Colombier Node *np;
1973e12c5d1SDavid du Colombier
1983e12c5d1SDavid du Colombier if(t != '(')
1993e12c5d1SDavid du Colombier return simple();
2003e12c5d1SDavid du Colombier np = alloc(xsubshell);
2013e12c5d1SDavid du Colombier t = gettoken();
2023e12c5d1SDavid du Colombier if((np->args[0]=list())==0 || t!=')')
2033e12c5d1SDavid du Colombier return 0;
2043e12c5d1SDavid du Colombier while((t=gettoken())=='<' || t=='>')
2053e12c5d1SDavid du Colombier if(!setio(np))
2063e12c5d1SDavid du Colombier return 0;
2073e12c5d1SDavid du Colombier return np;
2083e12c5d1SDavid du Colombier }
2093e12c5d1SDavid du Colombier
2103e12c5d1SDavid du Colombier /* getch - get next, possibly pushed back, input character */
2113e12c5d1SDavid du Colombier int
getch(void)2123e12c5d1SDavid du Colombier getch(void)
2133e12c5d1SDavid du Colombier {
2143e12c5d1SDavid du Colombier unsigned char c;
2153e12c5d1SDavid du Colombier static done=0;
2163e12c5d1SDavid du Colombier
2173e12c5d1SDavid du Colombier if(putback){
2183e12c5d1SDavid du Colombier c = putback;
2193e12c5d1SDavid du Colombier putback = 0;
2203e12c5d1SDavid du Colombier }else if(tflag){
2213e12c5d1SDavid du Colombier if(done || read(0, &c, 1)!=1){
2223e12c5d1SDavid du Colombier done = 1;
2233e12c5d1SDavid du Colombier return EOF;
2243e12c5d1SDavid du Colombier }
2253e12c5d1SDavid du Colombier if(c == '\n')
2263e12c5d1SDavid du Colombier done = 1;
2273e12c5d1SDavid du Colombier }else if(cflag){
2283e12c5d1SDavid du Colombier if(done)
2293e12c5d1SDavid du Colombier return EOF;
2303e12c5d1SDavid du Colombier if((c=*cflagp++) == 0){
2313e12c5d1SDavid du Colombier done = 1;
2323e12c5d1SDavid du Colombier c = '\n';
2333e12c5d1SDavid du Colombier }
2343e12c5d1SDavid du Colombier }else if(read(0, &c, 1) != 1)
2353e12c5d1SDavid du Colombier return EOF;
2363e12c5d1SDavid du Colombier return c;
2373e12c5d1SDavid du Colombier }
2383e12c5d1SDavid du Colombier
2393e12c5d1SDavid du Colombier /* gettoken - get next token into string space, return token code */
2403e12c5d1SDavid du Colombier int
gettoken(void)2413e12c5d1SDavid du Colombier gettoken(void)
2423e12c5d1SDavid du Colombier {
2433e12c5d1SDavid du Colombier int c;
2443e12c5d1SDavid du Colombier
2453e12c5d1SDavid du Colombier while((c = getch()) != EOF)
2463e12c5d1SDavid du Colombier if(!isspace(c))
2473e12c5d1SDavid du Colombier break;
2483e12c5d1SDavid du Colombier if(c==EOF || ispunct(c))
2493e12c5d1SDavid du Colombier return c;
2503e12c5d1SDavid du Colombier token = sfree;
2513e12c5d1SDavid du Colombier do{
2523e12c5d1SDavid du Colombier if(sfree >= strspace+sizeof(strspace) - 1){
2533e12c5d1SDavid du Colombier error("string storage overflow", "");
2543e12c5d1SDavid du Colombier exits("string storage overflow");
2553e12c5d1SDavid du Colombier }
2563e12c5d1SDavid du Colombier *sfree++ = c;
2573e12c5d1SDavid du Colombier }while((c=getch()) != EOF && !ispunct(c) && !isspace(c));
2583e12c5d1SDavid du Colombier *sfree++ = 0;
2593e12c5d1SDavid du Colombier putback = c;
2603e12c5d1SDavid du Colombier return WORD;
2613e12c5d1SDavid du Colombier }
2623e12c5d1SDavid du Colombier
2633e12c5d1SDavid du Colombier /* list - pipeline ( ( ; | & ) pipeline )* [ ; | & ] (not LL(1), but ok) */
2643e12c5d1SDavid du Colombier Node*
list(void)2653e12c5d1SDavid du Colombier list(void)
2663e12c5d1SDavid du Colombier {
2673e12c5d1SDavid du Colombier Node *np, *np1;
2683e12c5d1SDavid du Colombier
2693e12c5d1SDavid du Colombier np = alloc(0);
2703e12c5d1SDavid du Colombier if((np->args[1]=pipeline()) == 0)
2713e12c5d1SDavid du Colombier return 0;
2723e12c5d1SDavid du Colombier while(t==';' || t=='&'){
2733e12c5d1SDavid du Colombier np->op = (t==';')? xwait : xnowait;
2743e12c5d1SDavid du Colombier t = gettoken();
2753e12c5d1SDavid du Colombier if(t==')' || t=='\n') /* tests ~first(pipeline) */
2763e12c5d1SDavid du Colombier break;
2773e12c5d1SDavid du Colombier np1 = alloc(0);
2783e12c5d1SDavid du Colombier np1->args[0] = np;
2793e12c5d1SDavid du Colombier if((np1->args[1]=pipeline()) == 0)
2803e12c5d1SDavid du Colombier return 0;
2813e12c5d1SDavid du Colombier np = np1;
2823e12c5d1SDavid du Colombier }
2833e12c5d1SDavid du Colombier if(np->op == 0)
2843e12c5d1SDavid du Colombier np->op = xwait;
2853e12c5d1SDavid du Colombier return np;
2863e12c5d1SDavid du Colombier }
2873e12c5d1SDavid du Colombier
2883e12c5d1SDavid du Colombier /* error - print error message s, prefixed by t */
2893e12c5d1SDavid du Colombier void
error(char * s,char * t)2903e12c5d1SDavid du Colombier error(char *s, char *t)
2913e12c5d1SDavid du Colombier {
292*dc5a79c1SDavid du Colombier char buf[256];
2933e12c5d1SDavid du Colombier
2943e12c5d1SDavid du Colombier fprint(2, "%s%s", t, s);
295*dc5a79c1SDavid du Colombier errstr(buf, sizeof buf);
2963e12c5d1SDavid du Colombier fprint(2, ": %s\n", buf);
2973e12c5d1SDavid du Colombier }
2983e12c5d1SDavid du Colombier
2993e12c5d1SDavid du Colombier /* pipeline - command ( | command )* */
3003e12c5d1SDavid du Colombier Node*
pipeline(void)3013e12c5d1SDavid du Colombier pipeline(void)
3023e12c5d1SDavid du Colombier {
3033e12c5d1SDavid du Colombier Node *np, *np1;
3043e12c5d1SDavid du Colombier
3053e12c5d1SDavid du Colombier if((np=command()) == 0)
3063e12c5d1SDavid du Colombier return 0;
3073e12c5d1SDavid du Colombier while(t == '|'){
3083e12c5d1SDavid du Colombier np1 = alloc(xpipeline);
3093e12c5d1SDavid du Colombier np1->args[0] = np;
3103e12c5d1SDavid du Colombier t = gettoken();
3113e12c5d1SDavid du Colombier if((np1->args[1]=command()) == 0)
3123e12c5d1SDavid du Colombier return 0;
3133e12c5d1SDavid du Colombier np = np1;
3143e12c5d1SDavid du Colombier }
3153e12c5d1SDavid du Colombier return np;
3163e12c5d1SDavid du Colombier }
3173e12c5d1SDavid du Colombier
3183e12c5d1SDavid du Colombier /* redirect - redirect i/o according to np->io[] values */
3193e12c5d1SDavid du Colombier void
redirect(Node * np)3203e12c5d1SDavid du Colombier redirect(Node *np)
3213e12c5d1SDavid du Colombier {
3223e12c5d1SDavid du Colombier int fd;
3233e12c5d1SDavid du Colombier
3243e12c5d1SDavid du Colombier if(np->io[0]){
3253e12c5d1SDavid du Colombier if((fd = open(np->io[0], 0)) < 0){
3263e12c5d1SDavid du Colombier error(": can't open", np->io[0]);
3273e12c5d1SDavid du Colombier exits("open");
3283e12c5d1SDavid du Colombier }
3293e12c5d1SDavid du Colombier dup(fd, 0);
3303e12c5d1SDavid du Colombier close(fd);
3313e12c5d1SDavid du Colombier }
3323e12c5d1SDavid du Colombier if(np->io[1]){
3333e12c5d1SDavid du Colombier if((fd = create(np->io[1], 1, 0666L)) < 0){
3343e12c5d1SDavid du Colombier error(": can't create", np->io[1]);
3353e12c5d1SDavid du Colombier exits("create");
3363e12c5d1SDavid du Colombier }
3373e12c5d1SDavid du Colombier dup(fd, 1);
3383e12c5d1SDavid du Colombier close(fd);
3393e12c5d1SDavid du Colombier }
3403e12c5d1SDavid du Colombier if(np->io[2]){
3413e12c5d1SDavid du Colombier if((fd = open(np->io[2], 1)) < 0 && (fd = create(np->io[2], 1, 0666L)) < 0){
3423e12c5d1SDavid du Colombier error(": can't write", np->io[2]);
3433e12c5d1SDavid du Colombier exits("write");
3443e12c5d1SDavid du Colombier }
3453e12c5d1SDavid du Colombier dup(fd, 1);
3463e12c5d1SDavid du Colombier close(fd);
3473e12c5d1SDavid du Colombier seek(1, 0, 2);
3483e12c5d1SDavid du Colombier }
3493e12c5d1SDavid du Colombier }
3503e12c5d1SDavid du Colombier
3513e12c5d1SDavid du Colombier /* setio - ( < | > | >> ) word; fill in np->io[] */
3523e12c5d1SDavid du Colombier int
setio(Node * np)3533e12c5d1SDavid du Colombier setio(Node *np)
3543e12c5d1SDavid du Colombier {
3553e12c5d1SDavid du Colombier if(t == '<'){
3563e12c5d1SDavid du Colombier t = gettoken();
3573e12c5d1SDavid du Colombier np->io[0] = token;
3583e12c5d1SDavid du Colombier }else if(t == '>'){
3593e12c5d1SDavid du Colombier t = gettoken();
3603e12c5d1SDavid du Colombier if(t == '>'){
3613e12c5d1SDavid du Colombier t = gettoken();
3623e12c5d1SDavid du Colombier np->io[2] = token;
3633e12c5d1SDavid du Colombier }else
3643e12c5d1SDavid du Colombier np->io[1] = token;
3653e12c5d1SDavid du Colombier }else
3663e12c5d1SDavid du Colombier return 0;
3673e12c5d1SDavid du Colombier if(t != WORD)
3683e12c5d1SDavid du Colombier return 0;
3693e12c5d1SDavid du Colombier return 1;
3703e12c5d1SDavid du Colombier }
3713e12c5d1SDavid du Colombier
3723e12c5d1SDavid du Colombier /* simple - word ( [ < | > | >> ] word )* */
3733e12c5d1SDavid du Colombier Node*
simple(void)3743e12c5d1SDavid du Colombier simple(void)
3753e12c5d1SDavid du Colombier {
3763e12c5d1SDavid du Colombier Node *np;
3773e12c5d1SDavid du Colombier int n = 1;
3783e12c5d1SDavid du Colombier
3793e12c5d1SDavid du Colombier if(t != WORD)
3803e12c5d1SDavid du Colombier return 0;
3813e12c5d1SDavid du Colombier np = alloc(xsimple);
3823e12c5d1SDavid du Colombier np->argv[0] = token;
3833e12c5d1SDavid du Colombier while((t = gettoken())==WORD || t=='<' || t=='>')
3843e12c5d1SDavid du Colombier if(t == WORD)
3853e12c5d1SDavid du Colombier np->argv[n++] = token;
3863e12c5d1SDavid du Colombier else if(!setio(np))
3873e12c5d1SDavid du Colombier return 0;
3883e12c5d1SDavid du Colombier np->argv[n] = 0;
3893e12c5d1SDavid du Colombier return np;
3903e12c5d1SDavid du Colombier }
3913e12c5d1SDavid du Colombier
3923e12c5d1SDavid du Colombier /* xpipeline - execute cmd | cmd */
3933e12c5d1SDavid du Colombier int
xpipeline(Node * np)3943e12c5d1SDavid du Colombier xpipeline(Node *np)
3953e12c5d1SDavid du Colombier {
3963e12c5d1SDavid du Colombier int pid, fd[2];
3973e12c5d1SDavid du Colombier
3983e12c5d1SDavid du Colombier if(pipe(fd) < 0){
3993e12c5d1SDavid du Colombier error("can't create pipe", "");
4003e12c5d1SDavid du Colombier return 0;
4013e12c5d1SDavid du Colombier }
4023e12c5d1SDavid du Colombier if((pid=fork()) == 0){ /* left side; redirect stdout */
4033e12c5d1SDavid du Colombier dup(fd[1], 1);
4043e12c5d1SDavid du Colombier close(fd[0]);
4053e12c5d1SDavid du Colombier close(fd[1]);
4063e12c5d1SDavid du Colombier execute(np->args[0]);
407*dc5a79c1SDavid du Colombier exits(status);
4083e12c5d1SDavid du Colombier }else if(pid == -1){
4093e12c5d1SDavid du Colombier error("can't create process", "");
4103e12c5d1SDavid du Colombier return 0;
4113e12c5d1SDavid du Colombier }
4123e12c5d1SDavid du Colombier if((pid=fork()) == 0){ /* right side; redirect stdin */
4133e12c5d1SDavid du Colombier dup(fd[0], 0);
4143e12c5d1SDavid du Colombier close(fd[0]);
4153e12c5d1SDavid du Colombier close(fd[1]);
4163e12c5d1SDavid du Colombier pid = execute(np->args[1]); /*BUG: this is wrong sometimes*/
4173e12c5d1SDavid du Colombier if(pid > 0)
418*dc5a79c1SDavid du Colombier while(waitpid()!=pid)
4193e12c5d1SDavid du Colombier ;
4203e12c5d1SDavid du Colombier exits(0);
4213e12c5d1SDavid du Colombier }else if(pid == -1){
4223e12c5d1SDavid du Colombier error("can't create process", "");
4233e12c5d1SDavid du Colombier return 0;
4243e12c5d1SDavid du Colombier }
4253e12c5d1SDavid du Colombier close(fd[0]); /* avoid using up fd's */
4263e12c5d1SDavid du Colombier close(fd[1]);
4273e12c5d1SDavid du Colombier return pid;
4283e12c5d1SDavid du Colombier }
4293e12c5d1SDavid du Colombier
4303e12c5d1SDavid du Colombier /* xsimple - execute a simple command */
4313e12c5d1SDavid du Colombier int
xsimple(Node * np)4323e12c5d1SDavid du Colombier xsimple(Node *np)
4333e12c5d1SDavid du Colombier {
4343e12c5d1SDavid du Colombier char name[MAXLINE];
4353e12c5d1SDavid du Colombier int pid, i;
4363e12c5d1SDavid du Colombier
4373e12c5d1SDavid du Colombier if(builtin(np))
4383e12c5d1SDavid du Colombier return 0;
4393e12c5d1SDavid du Colombier if(pid = fork()){
4403e12c5d1SDavid du Colombier if(pid == -1)
4413e12c5d1SDavid du Colombier error(": can't create process", np->argv[0]);
4423e12c5d1SDavid du Colombier return pid;
4433e12c5d1SDavid du Colombier }
4443e12c5d1SDavid du Colombier redirect(np); /* child process */
4453e12c5d1SDavid du Colombier exec(np->argv[0], &np->argv[0]);
4463e12c5d1SDavid du Colombier i = np->argv[0][0];
4473e12c5d1SDavid du Colombier if(i!='/' && i!='#' && (i!='.' || np->argv[0][1]!='/'))
4483e12c5d1SDavid du Colombier for(i = 0; path[i]; i++){
4493e12c5d1SDavid du Colombier sprint(name, "%s/%s", path[i], np->argv[0]);
4503e12c5d1SDavid du Colombier exec(name, &np->argv[0]);
4513e12c5d1SDavid du Colombier }
4523e12c5d1SDavid du Colombier error(": not found", np->argv[0]);
4533e12c5d1SDavid du Colombier exits("not found");
454*dc5a79c1SDavid du Colombier return -1; // suppress compiler warnings
4553e12c5d1SDavid du Colombier }
4563e12c5d1SDavid du Colombier
4573e12c5d1SDavid du Colombier /* xsubshell - execute (cmd) */
4583e12c5d1SDavid du Colombier int
xsubshell(Node * np)4593e12c5d1SDavid du Colombier xsubshell(Node *np)
4603e12c5d1SDavid du Colombier {
4613e12c5d1SDavid du Colombier int pid;
4623e12c5d1SDavid du Colombier
4633e12c5d1SDavid du Colombier if(pid = fork()){
4643e12c5d1SDavid du Colombier if(pid == -1)
4653e12c5d1SDavid du Colombier error("can't create process", "");
4663e12c5d1SDavid du Colombier return pid;
4673e12c5d1SDavid du Colombier }
4683e12c5d1SDavid du Colombier redirect(np); /* child process */
4693e12c5d1SDavid du Colombier execute(np->args[0]);
470*dc5a79c1SDavid du Colombier exits(status);
471*dc5a79c1SDavid du Colombier return -1; // suppress compiler warnings
4723e12c5d1SDavid du Colombier }
4733e12c5d1SDavid du Colombier
4743e12c5d1SDavid du Colombier /* xnowait - execute cmd & */
4753e12c5d1SDavid du Colombier int
xnowait(Node * np)4763e12c5d1SDavid du Colombier xnowait(Node *np)
4773e12c5d1SDavid du Colombier {
4783e12c5d1SDavid du Colombier int pid;
4793e12c5d1SDavid du Colombier
4803e12c5d1SDavid du Colombier execute(np->args[0]);
4813e12c5d1SDavid du Colombier pid = execute(np->args[1]);
4823e12c5d1SDavid du Colombier if(interactive)
4833e12c5d1SDavid du Colombier fprint(2, "%d\n", pid);
4843e12c5d1SDavid du Colombier return 0;
4853e12c5d1SDavid du Colombier }
4863e12c5d1SDavid du Colombier
4873e12c5d1SDavid du Colombier /* xwait - execute cmd ; */
xwait(Node * np)4883e12c5d1SDavid du Colombier int xwait(Node *np)
4893e12c5d1SDavid du Colombier {
4903e12c5d1SDavid du Colombier int pid;
491*dc5a79c1SDavid du Colombier Waitmsg *wmsg;
4923e12c5d1SDavid du Colombier
4933e12c5d1SDavid du Colombier execute(np->args[0]);
4943e12c5d1SDavid du Colombier pid = execute(np->args[1]);
4953e12c5d1SDavid du Colombier if(pid > 0){
496*dc5a79c1SDavid du Colombier while((wmsg = wait()) != nil){
497*dc5a79c1SDavid du Colombier if(wmsg->pid == pid)
498*dc5a79c1SDavid du Colombier break;
499*dc5a79c1SDavid du Colombier free(wmsg);
500*dc5a79c1SDavid du Colombier }
501*dc5a79c1SDavid du Colombier if(wmsg == nil)
5023e12c5d1SDavid du Colombier error("wait error", "");
503*dc5a79c1SDavid du Colombier else {
504*dc5a79c1SDavid du Colombier strncpy(status, wmsg->msg, sizeof(status)-1);
505*dc5a79c1SDavid du Colombier free(wmsg);
506*dc5a79c1SDavid du Colombier }
5073e12c5d1SDavid du Colombier }
5083e12c5d1SDavid du Colombier return 0;
5093e12c5d1SDavid du Colombier }
510