250 lines
6.4 KiB
C
250 lines
6.4 KiB
C
/*
|
|
* 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 ; i<SYMTBLSIZE ; i++) symTable[i] = NULL;
|
|
place=0;
|
|
}
|
|
|
|
/*Exekverar varje kommando som en egen process*/
|
|
void cmd(treePtr tPtr) {
|
|
int pid, status;
|
|
switch(pid=fork()){
|
|
case -1: printf("Could not fork. (cmd)\n"); break;
|
|
case 0: if((execvp(symTable[tPtr->index], &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;
|
|
}
|
|
|