#include #include #include #include #include #include #include #include char* substr(const char *src, int m, int n); void pipeFunc(char *command1, char *command2); int main() { while (1) { printf("My Shell\n"); printf(">> "); //following is the temporary string that I want to keep my char[] read from breaking the above char[] myString //following breaks based on space character char commandStr[100], commandStrFull[100]; char *temp; char *temp2; char temp3[100]; //strcpy(commandStr, "exit"); fgets(commandStr, 100, stdin); //strcpy(commandStr, "ls -l > a.txt"); strcpy(commandStrFull,commandStr); char *filename; int flag = 0; // exit program if command is exit if(strcmp(commandStr, "exit\n")==0) { exit(-1); } int redir=0; int redirIndex; int pipeNum=0; int single=0; char* redirCheckTwo=NULL; char* command2; char* command1; char* pipeCheck = strchr(commandStr, '|'); char* redirCheck = strchr(commandStr, '>'); if(pipeCheck!=NULL) { pipeNum=1; redirCheckTwo = strchr(commandStr, '>'); command1 = strrchr(commandStr, '|'); redirIndex = strcspn(commandStr, ">"); } else single=1; if (redirCheckTwo!=NULL) { command1 = strrchr(commandStr, '|'); redir=1; } if(redirCheck!=NULL) redir=1; //commandStr[strcspn(commandStr, "\n")] = 0; // pipe or redirect if (pipeNum==1 || redir==1) { temp = strtok(commandStr," "); //include , inside "" while(temp!=NULL) { //printf("%s\n",temp); if (strcmp(temp,">")==0 && redir==1) { filename = strtok(NULL, " "); //printf("Filename: %s\n", filename); } if (strcmp(temp,"|")==0 && pipeCheck!=NULL) { command2 = strtok(NULL," >"); //puts(strchr(temp, '|')); flag=1; } if (pipeNum==1 || redir==1) { temp = strtok(NULL," "); //include , inside "" } else temp2 = strtok(NULL," "); //include , inside "" } } // single command is run if(single==1 && pipeNum==0 && redir==0){ commandStr[strcspn(commandStr, "\n")] = 0; //strcpy(temp,commandStr); //execvp expects the arguments to be provided as char[][] //so please make sure you understand strtok before coming here //we will use strtok() to break the sequence of command and argument in myArgument to convert to char[][] char* myBrokenArgs[10]; //this will hold the values after we tokenize //printf("Starting tokenization...\n"); myBrokenArgs[0] = strtok(commandStr," "); int counter = 0; while(myBrokenArgs[counter]!=NULL) { counter+=1; myBrokenArgs[counter] = strtok(NULL," "); } myBrokenArgs[counter] = NULL; //printf("\ttokenization complete....\n\nNow executing using execvp\n"); //printf("Following will be the output of execvp\n"); //printf("=======================================\n"); if ((strcmp("ls",myBrokenArgs[0]) ==0) && single==1) { int id; //I will spawn a child that will run my execvp command if((id=fork())==0) execvp(myBrokenArgs[0],myBrokenArgs); else if(id<0) printf("Failed to make child...\n"); else { //parent shall wait until the child is killed wait(0); printf("=======================================\n"); printf("Completed execution\n"); } } else if (strcmp("date",myBrokenArgs[0]) ==0) { int id; //I will spawn a child that will run my execvp command if((id=fork())==0) execvp(myBrokenArgs[0],myBrokenArgs); else if(id<0) printf("Failed to make child...\n"); else { //parent shall wait until the child is killed wait(0); printf("=======================================\n"); printf("Completed execution\n"); } } else if ((strcmp("ps",myBrokenArgs[0]) ==0)) { int id; //I will spawn a child that will run my execvp command if((id=fork())==0) execvp(myBrokenArgs[0],myBrokenArgs); else if(id<0) printf("Failed to make child...\n"); else { //parent shall wait until the child is killed wait(0); printf("=======================================\n"); printf("Completed execution\n"); } } } // pipe is used if (pipeNum==1 && redirCheck==NULL && single==0) { strcpy(commandStrFull, "ls -lah | wc -l"); int size = strcspn(commandStrFull, "|"); int end = strcspn(commandStrFull, "\0"); int beg = strcspn(commandStrFull, "|"); char* command2 = substr(commandStrFull, beg+2, end); end = strcspn(commandStrFull, "|"); char* command1 = substr(commandStrFull, 0, end-1); char* command1Args[10]; //this will hold the values after we tokenize //printf("Starting tokenization...\n"); command1Args[0] = strtok(command1," "); int counter = 0; while(command1Args[counter]!=NULL) { counter+=1; command1Args[counter] = strtok(NULL,"\0"); } command1Args[counter] = NULL; char* command2Args[10]; //this will hold the values after we tokenize //printf("Starting tokenization...\n"); command2Args[0] = strtok(command2," "); counter = 0; while(command2Args[counter]!=NULL) { counter+=1; command2Args[counter] = strtok(NULL," "); } command2Args[counter] = NULL; int fds[2]; pipe(fds); // Child 1 will duplicate downstream into stdin if(fork() == 0) { dup2(fds[0], 0); // normally 0 is for stdin // will now read to fds[0] // end of pipe close(fds[1]); // close other end of pipe execlp(command2Args[0] ,command2Args[0], command2Args, 0); //execlp("wc", "wc", "-l", 0); // Note the first argument is the command // After it are the arguments including // original command } // Child2 duplicates upstream into stdout else if (fork() == 0) { dup2(fds[1], 1); // normally 1 is for stdout // will now write to fds[1] // end of pipe close(fds[0]); // close other end of pipe execlp(command1Args[0],command1Args[0], command1Args, 0); } // Parent else { close(fds[0]); close(fds[1]); wait(0); wait(0); } } if (pipeNum==0 && redir==1) { int end = strcspn(commandStrFull, ">"); int beg = strcspn(commandStrFull, "|"); char* command1 = substr(commandStrFull, 0, end-1); char* myBrokenArgs[10]; //this will hold the values after we tokenize printf("Starting tokenization...\n"); myBrokenArgs[0] = strtok(command1," "); int counter = 0; while(myBrokenArgs[counter]!=NULL) { counter+=1; myBrokenArgs[counter] = strtok(NULL," "); } myBrokenArgs[counter] = NULL; int myDescriptor = open(filename,O_CREAT|O_RDWR|O_TRUNC,0644); int id; //creating a child that redirects the stdout to test.txt // you can use similar functionality for '>' operator if((id=fork())==0) { //lets call dup2 so that out stdout (second argument) is now copied to (points to) test.txt (first argument) // what this essentially means is that anything that you send to stdout will be sent to myDescriptor dup2(myDescriptor,1); //1 is stdout, 0 is stdin and 2 is stderr execvp(myBrokenArgs[0],myBrokenArgs); close(myDescriptor); exit(0); }else wait(0); printf("Completed execution.\n"); } } return 0; } void pipeFunc(char *command1, char *command2) { } char* substr(const char *src, int m, int n) { // get the length of the destination string int len = n - m; // allocate (len + 1) chars for destination (+1 for extra null character) char *dest = (char*)malloc(sizeof(char) * (len + 1)); // start with m'th char and copy `len` chars into the destination strncpy(dest, (src + m), len); // return the destination string return dest; }