1 /* Minimal shell C source - (c) 1999, Spock (Oscar Portela Arjona) */
10 #define chkerr(c,msg) if (c < 0) {perror("ERROR (" msg ")"); exit(-1);}
11 #define mvdesc(d1,d2) {close(d1); dup(d2); close(d2);}
12 #define redir(n,f) {close(n); chkerr(open(fv[n],f,0666),"open");}
13 #define size(v,s,u,n) {(v = realloc(v,s))[u] = n;}
18 char ***l1 = NULL, *fv[3] ,dir[50] ,c;
19 int vc, bg, id, p[2], d;
21 signal(SIGINT, SIG_IGN); signal(SIGQUIT,SIG_IGN);
24 getcwd(dir,50); write(1,dir,strlen(dir)); write(1," $ ",d = bg = 3);
25 for (;bg; fv[bg] = NULL) realloc(fv[--bg],0); size(l1,4,0,NULL);
26 for (vc = p[0] = 0; read(0,&c,1) && (c != '\n');)
28 case '<': d = 0; break;
29 case '>': d = 1; break;
30 case '|': if (l2) {vc++; p[0] = 0;} d = 3; break;
31 case '&': if (d < 3) d++; else bg = 1; break;
32 case ' ': if (d < 3) {if (fv[d]) d = 3;} else if (l2 && l3) p[0]++; break;
33 default: if (d < 3) {if (!fv[d]) size(fv[d],1,0,'\0');
34 size(fv[d],(id=strlen(fv[d]))+2,id,c); fv[d][id+1]='\0';}
35 else { if (!l2) {size(l1,vc*4+8,vc+1,NULL); size(l2,4,0,NULL);}
36 if (!l3) {size(l2,p[0]*4+8,p[0]+1,NULL); size(l3,1,0,'\0');}
37 size(l3,(id=strlen(l3))+2,id,c); l3[id+1] = '\0';}}
41 if (l1[vc+1]) chkerr(pipe(p),"pipe");
42 if (!strcmp(l2[0],"exit")) exit(0);
43 if (!strcmp(l2[0],"cd")) {if (chdir(l2[1]) < 0) chdir(getenv("HOME"));}
44 else {if (!(id = fork())) {
45 if (fv[0] && !vc) redir(0,O_RDONLY) else mvdesc(0,d);
46 if (fv[1]) redir(1,O_CREAT|O_WRONLY|O_TRUNC);
47 if (fv[2]) redir(2,O_CREAT|O_WRONLY|O_TRUNC);
48 if (l1[vc+1]) {mvdesc(1,p[1]); close(p[0]);}
49 if (!bg) {signal(SIGINT,SIG_DFL); signal(SIGQUIT,SIG_DFL);}
50 chkerr(execvp(l2[0],l2),"exec");}
51 if (!l1[vc+1] && !bg) while (wait(NULL) != id);}
52 for (id = 0; l2[id]; realloc(l2[id++],0)); realloc(l2,0);
53 close(d); if (l1[++vc]) {d = dup(p[0]); close(p[0]); close(p[1]);}}}}