1
0
UAHCode/CPE435/Lab3/shell.c

278 lines
7.7 KiB
C
Raw Normal View History

2022-08-28 21:12:16 +00:00
#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;
}