/** * @file * * Fool's Shell * ========= * * A minimalsitic and naive shell developed along the Fool OS kernel. * TODO: Free tokenizer / dynamic size! * TODO: & with pipes * TODO: > < * TODO: tab complete * TODO: multiple PATH vars * TODO: history */ #include #include #include #include #include #include #include "interface/fs.h" extern char **environ; bool process(char *buf); bool metaprocess(char *buf); bool cd(char *path); void version() { puts("Fool's Shell version git-commit:" GIT_REVISION "\ncompiled on " __DATE__ " at " __TIME__); } void help() { puts( "\nfoolshell: supported built-in commands/functions:\n\n" "'env' - show all environment variables\n" "'getenv [var]' - show environment variable\n" "'setenv [var] [val]' - set environemnet variable\n" "'cd [dir]' - change directory (set $PWD)\n" "'[binary] [params...]' - run a binary\n" "'[binary] [params...] &' - run a binary in background\n" " | - pipes\n" "'help' - show this message\n" "'exit' - exit running foolshell\n\n"); } void prompt() { printf("\033[36mfool\033[37m@\033[32mhill\033[33m:%s%s\033[37m",getenv("PWD"),getenv("PS1")); } int main(int argc, char **argv) { for(int i=0;i\n",c, token[c]); c++; token[c]=NULL; } return token; } bool metaprocess2(char *buf); bool metaprocess(char *buf) { char **token=tokenize(buf,'|'); if(token[0]==0 || token[1]==0)return process(buf); // no pipes int pid=_fork(); if(pid==0) { metaprocess2(buf); exit(1); } _wait(pid); return true; } bool metaprocess2(char *buf) { char **token=tokenize(buf,'|'); if(token[0]==0 || token[1]==0)return process(buf); // no pipes int fds[2]; _pipe(fds); int pid=_fork(); if(pid==0) { // first child shall write to the pipe _close(fds[0]); _dup2(fds[1],1); // replace stdout with the write-end of our pipe process(token[0]); exit(1); } _close(fds[1]); // and we read from it _dup2(fds[0],0); metaprocess2(strchr(buf,'|')+1); _wait(pid); return true; } bool process(char *buf) { char **token=tokenize(buf,' '); char *command=token[0]; if(!strcmp(command,"help"))help(); else if(!strcmp(command,"cd"))cd(token[1]); else if(!strcmp(command,"exit")) return false; //else if(!strcmp(command,"getenv"))printf("(0x%08X) get: '%s' = '%s'(0x%08X) \n",environ,token[1],getenv(token[1]),getenv(token[1])); else if(!strcmp(command,"getenv"))printf("%s\n",getenv(token[1])); else if(!strcmp(command,"setenv")) { sprintf(buf,"%s=%s",token[1],token[2]); putenv(buf); //printf("(0x%08X) set: '%s' = '%s' \n",environ,token[1],getenv(token[1])); } else if(!strcmp(command,"env")) { int i=0; // printf("env: 0x%08X\n",environ); while(environ[i]!=NULL) { // printf("envvar %s (0x%08X)\n" ,environ[i],environ[i]); printf("%s\n" ,environ[i]); i++; } } else // otherwise treat command as exectutable and send to execve { int last=0; for(last=0;token[last+1]!=NULL;last++); bool branch=!strcmp(token[last],"&"); if(branch)token[last]=NULL; int pid=_fork(); if(pid==0) { if(token[0][0]=='/')sprintf(buf,"%s",token[0]); else sprintf(buf,"%s/%s",getenv("PATH"),token[0]); _execve(buf,token,environ); printf("foolshell: %s (errno: %d)\n",strerror(errno),errno); exit(1); } //printf("last: %s\n",token[last]); if(!branch)_wait(pid); } return true; } bool setpwd(char *path) { if(!strcmp(path,"/")) { putenv("PWD=/"); return true; } char buf[255]; buf[0]=0; strcat(buf,"PWD="); char **t=tokenize(path,'/'); char *p[100]; int pp=0; while(*t!=NULL) { if(!strcmp(*t,"..")){ pp--; t++; if(pp<0)pp=0; continue; } if(!strcmp(*t,".")){t++; continue;} if(**t!=0) { p[pp]=*t; //printf("> %s\n",p[pp]); pp++; } t++; } if(pp==0) { strcat(buf,"/"); } for(int i=0;i