/* * Laboration 2 i C och UNIX * * Komplett shell * ========================================= * * Christian Ohlsson, di7chro@cse.kau.se * Stefan Sonesson, di7stes@cse.kau.se * * Karlstads Universitet, 991209 * * *=========================================== */ #include "lab2.h" extern treePtr tree; /*Array med alla inmatningar som gjorts*/ char *symTable[SYMTBLSIZE]; /*Global räknare för symTable*/ int place=0; /*Kopierar alla WORD & NULL till symTable*/ int insert(char *str){ if(str) symTable[place]=(char*)strdup(str); else symTable[place]=str; return place++; } /*Rensar symTable*/ void delTable() { int i=0; for(i=0 ; iindex], &symTable[tPtr->index])) == -1) { fprintf(stderr, "Could not execute that.\n"); exit(1); /* Child */ } exit(1); break; default: if((waitpid(pid, &status,0)) == -1) { /* Parent */ fprintf(stderr, "Could not wait. (cmd)\n"); return; /*exit(1);*/ } break; } } /*Hanterar pipes och ställer om fildescriptorer*/ void pipa(treePtr tPtr) { int status, pfd[2]; if((pipe(pfd)) == -1) { fprintf(stderr, "Pipe failed. (pipa) \n"); return; } switch(fork()) { case -1: fprintf(stderr, "Fork failed. (pipa)\n");break; case 0 : if((dup2(pfd[1], 1)) == -1) { /* Child 1 */ fprintf(stderr, "Could not dup.(pipa)\n"); exit(1); } if((close(pfd[0])) == -1) { fprintf(stderr, "Could not close filedescriptor.(pipa)\n"); exit(1); } doTree(tPtr->left); exit(1); break; default: /* Parent 1 */ switch(fork()) { case -1: fprintf(stderr, "Fork failed(pipa)\n");break; case 0 : if((dup2(pfd[0], 0)) == -1) { /* Child 2 */ fprintf(stderr, "Could not dup(pipa).\n"); exit(1); } if((close(pfd[1])) == -1) { fprintf(stderr, "Could not close filedescriptor.(pipa)\n"); exit(1); } doTree(tPtr->right); exit(1); break; default: if((close(pfd[0])) == -1) { /* Parent 2 */ fprintf(stderr, "Could not close filedescriptor 0.(pipa)\n"); exit(1); } if((close(pfd[1])) == -1) { fprintf(stderr, "Could not close filedescriptor 1.(pipa)\n"); exit(1); } if((wait(&status)) == -1) { fprintf(stderr, "Could not wait.(pipa)\n"); exit(1); } if((wait(&status)) == -1) { fprintf(stderr, "Could not wait.(pipa)\n"); exit(1); } break; } break; } } /*Hanterar semikolon, Kör vänster-delen om semikolonet, och när det är klart körs högerdelen*/ void semi(treePtr tPtr) { int status; switch(fork()) { case -1: fprintf(stderr, "Fork failed. (semi)\n");break; case 0 : doTree(tPtr->left); /* Child */ exit(1); break; default: if((wait(&status)) == -1) { /* Parent */ fprintf(stderr, "Could not wait.(semi)\n"); exit(-1); } if(tPtr->right) doTree(tPtr->right); break; } } /*Ställer om utmatningsfil från STDOUT till utfil Om filen finns, trunkeras den*/ void great(treePtr tPtr) { int fd, status; if((fd=open(symTable[tPtr->right->index],O_CREAT|O_TRUNC|O_WRONLY, PERMS))==-1) { fprintf(stderr, "Could not open file. (great)\n"); exit(1); } switch(fork()) { case -1: fprintf(stderr, "Fork failed\n"); break; case 0 : if((dup2(fd, 1)) == -1) { /* Child */ fprintf(stderr, "Could not dup. (great)\n"); exit(1); } doTree(tPtr->left); exit(1); break; default: if((wait(&status)) == -1) { /* Parent */ fprintf(stderr, "Could not wait. (great)\n"); exit(1); } break; } if((close(fd)) == -1) { fprintf(stderr, "Could not close file. (great)\n"); exit(1); } } /*Ställer om indirigering från STDIN till fil*/ void less(treePtr tPtr) { int fd, status; if((fd=open(symTable[tPtr->right->index], O_RDONLY, PERMS))==-1){ fprintf(stderr, "Could not open file (less)\n"); return; } switch(fork()) { case -1: fprintf(stderr, "Fork failed\n"); break; case 0 : if((dup2(fd, 0)) == -1) { /* Child */ fprintf(stderr, "Could not dup.(less)\n"); exit(1); } doTree(tPtr->left); exit(1); break; default: if((wait(&status)) == -1) { /* Parent */ fprintf(stderr, "Could not wait.(less)\n"); exit(1); } break; } if((close(fd)) == -1) { fprintf(stderr, "Could not close file.(less)\n"); exit(1); } } /*Kör processer utan att de behöver invänta den andre*/ void and(treePtr tPtr) { int status; switch(fork()) { case -1: fprintf(stderr, "Fork failed. (and)\n");break; case 0: if(tPtr->left) doTree(tPtr->left); /* Child */ exit(0); break; default: if(tPtr->right) doTree(tPtr->right); /* Parent */ break; } } /*Ställer om utmatningsfil från STDOUT till utfil Om filen finns, appendas den*/ void dblarr(treePtr tPtr) { int fd, status; if((fd=open(symTable[tPtr->right->index],O_CREAT|O_APPEND|O_WRONLY, PERMS))==-1) { fprintf(stderr, "Could not open file. (dblarr)\n"); exit(1); } switch(fork()) { case -1: fprintf(stderr, "Fork failed\n"); break; case 0: if((dup2(fd, 1)) == -1) { fprintf(stderr, "Could not dup. (dblarr)\n"); exit(1); } doTree(tPtr->left); exit(1); break; default: if((wait(&status)) == -1) { fprintf(stderr, "Could not wait. (dblarr)\n"); exit(1); } break; } if((close(fd)) == -1) { fprintf(stderr, "Could not close file. (dblarr)\n"); exit(1); } } /*Anropar rätt funktion beroende på metatecken*/ void doTree(treePtr tPtr) { if(tPtr->nodeType == 0) cmd(tPtr); if(tPtr->nodeType == PIPE) pipa(tPtr); if(tPtr->nodeType == SEMI) semi(tPtr); if(tPtr->nodeType == GREAT) great(tPtr); if(tPtr->nodeType == LESS) less(tPtr); if(tPtr->nodeType == AND) and(tPtr); if(tPtr->nodeType == DBLARR) dblarr(tPtr); delTable(); } /*Anropar Lex och Yacc med yyparse och sedan exeveras trädet*/ int main() { signal(SIGTERM, SIG_IGN); signal(SIGKILL, SIG_IGN); signal(SIGCHLD,SIG_IGN); signal(SIGINT,SIG_IGN); system("clear"); write(1, "Welcome to WARPshell 1.0\n",26); while(1) { fflush(stdout); write(1,"C:\\> ",5); yyparse(); if(tree) doTree(tree); } return 1; }