278 lines
7.7 KiB
C
278 lines
7.7 KiB
C
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <unistd.h>
|
||
|
#include <sys/wait.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <fcntl.h>
|
||
|
#include <string.h>
|
||
|
#include <sys/wait.h>
|
||
|
|
||
|
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;
|
||
|
}
|