diff --git a/bin/.keep b/bin/.keep new file mode 100644 index 0000000..e69de29 diff --git a/include/Common.h b/include/Common.h index 25ac07a..bda50d1 100755 --- a/include/Common.h +++ b/include/Common.h @@ -1,11 +1,15 @@ #ifndef COMMON_H #define COMMON_H +const char* GetHomeDir(void); + typedef struct CommandStruct { char* argv[100]; // Max 100 commands int argc; + char* envp[20]; // Enviroment Varibles } CommandStruct; +void CopyCommandStruct(CommandStruct* oldCommand, CommandStruct* newCommand, int start, int end); void ResetCommandStruct(CommandStruct* command); -#endif \ No newline at end of file +#endif diff --git a/include/Integrated.h b/include/Integrated.h index ecfd85f..e3c66a9 100755 --- a/include/Integrated.h +++ b/include/Integrated.h @@ -3,15 +3,16 @@ #include "Common.h" -const char* GetHomeDir(void); -void ioRedirection(CommandStruct *command); +void CheckRedirection(CommandStruct* command); +int CheckSymbol(CommandStruct* command, char symbol, int start); +int CountSymbol(CommandStruct* command, char symbol); int IntegratedCheck(CommandStruct* command); void GetInput(char* inputString); void append(char *input, char *file); void input(char *command); -void ExecPipe(); +int ExecPipe(CommandStruct* commandParent, CommandStruct* commandChild, int* pipefd); void output(char *command); -void ParseInput(char* inputString, CommandStruct* command); -void ReadPishrc(CommandStruct* command, char* inputString); - -#endif \ No newline at end of file +void SplitInput(char* inputString, CommandStruct* command); +void ParseInput(char* inputString, CommandStruct* command, char* symbol); +void ioRedirection(CommandStruct* command); +#endif diff --git a/include/Pish.h b/include/Pish.h index 9b54a1a..d42d669 100644 --- a/include/Pish.h +++ b/include/Pish.h @@ -4,5 +4,7 @@ #include "Common.h" void Pish(void); +void ReadPishrc(CommandStruct* commandParent, CommandStruct *commandChild, char* inputString); +void RunChild(CommandStruct* commandChild, int* pipefd); #endif diff --git a/src/Common.c b/src/Common.c index 1f230a8..74b79a3 100644 --- a/src/Common.c +++ b/src/Common.c @@ -1,7 +1,28 @@ #include "Common.h" +#include #include #include +#include +#include + +// Gets home directory location of user +const char* GetHomeDir(void) +{ + char *homeDir = (getpwuid(getuid()))->pw_dir; + return homeDir; +} + +// Copies a range of an old command object to new command object +void CopyCommandStruct(CommandStruct* oldCommand, CommandStruct* newCommand, int start, int end) +{ + newCommand->argc = end - start; + for (int i = 0; i < newCommand->argc; i++) + newCommand->argv[i] = oldCommand->argv[i + start]; + return; +} + +// Resets entire command object void ResetCommandStruct(CommandStruct* command) { for (int i = 0; i < command->argc; i++) diff --git a/src/Integrated.c b/src/Integrated.c index 3722651..c676849 100755 --- a/src/Integrated.c +++ b/src/Integrated.c @@ -1,22 +1,13 @@ #include #include -#include #include #include #include #include #include -#include #include #include "Integrated.h" -// Gets home directory location of user -const char *GetHomeDir(void) -{ - char *homeDir = (getpwuid(getuid()))->pw_dir; - return homeDir; -} - // Checks for commands that are built into Pish int IntegratedCheck(CommandStruct *command) { @@ -43,94 +34,119 @@ void GetInput(char *inputString) printf("%s ", prompt); // assert(scanf("%[^\n]s", inputString) == 1); scanf("%1000[^\n]s", inputString); - while ((c = getchar()) != '\n' && c != EOF) + while ((c = getchar()) != '\n' && c != EOF) // Cleans input /* discard */; return; } // Splits a string separated by spaces into an array of strings -void ParseInput(char *inputString, CommandStruct *command) +void ParseInput(char *inputString, CommandStruct *command, char *symbol) { // Parse command int *argc = &(command->argc); - char *token = strtok(inputString, " "); + char *token = strtok(inputString, symbol);//change command->argv[*argc] = token; (*argc)++; while (token != NULL) { // This only holds 1 command at a time then it overrides // Will need modified - token = strtok(NULL, " "); + token = strtok(NULL, symbol);//change command->argv[*argc] = token; (*argc)++; } } -// Reads ~/.pishrc and runs each command in the file -void ReadPishrc(CommandStruct *command, char *inputString) +// Splits a string separated by spaces into an array of strings +void SplitInput(char *inputString, CommandStruct *command) { - char buffer[1]; - int forkID; int *argc = &(command->argc); - char* pishLocation = GetHomeDir(); - strcat(pishLocation, "/.pishrc"); - int fd = open(pishLocation, O_RDONLY | O_CREAT); - assert(fd > -1); - while (read(fd, buffer, 1) > 0) + char *token = strtok(inputString, " "); + command->argv[*argc] = token; + (*argc)++; + while (token != NULL) { - if (buffer[0] == '\n') - { - ParseInput(inputString, command); - forkID = fork(); - if (forkID == 0) - execvp(command->argv[0], command->argv); - else - wait(&forkID); - strcpy(inputString, ""); - ResetCommandStruct(command); - continue; - } - strcat(inputString, buffer); + token = strtok(NULL, " "); + command->argv[*argc] = token; + (*argc)++; } - assert(close(fd) >= 0); + (*argc)--; } -// i/o redirection -// TODO: Work on one symbol at a time -// inputString may not be useful here, only *command -// Try to add a layer of abstraction where possible -// I.E. think about using function instead for checking -void ioRedirection(CommandStruct *command) +// Splits a command array into left and right +// void SplitPipe(CommandStruct* commandLeft, CommandStruct* commandRight); + +int CheckSymbol(CommandStruct* command, char symbol, int start) { - int newfd; - // check command standard output + for (int i = start; i < command->argc; i++) + if (command->argv[i][0] == symbol) + return i; + return -1; +} + +// Checking redirection +void CheckRedirection(CommandStruct* command) +{ + // check command standard output // TODO: Check command->argv[] for symbol instead - for(int i = 0; i < sizeof(command); i++) - { - if (strchr(command->argv[i], '>') != NULL) - { - output(command->argv[i+1]); - // Check if targeting a specific string in command->argv works - } - if (strchr(command->argv[i], '<') != NULL) - { - input(command->argv[i+1]); - } - if (strchr(command->argv[i], '|')!= NULL) - { - // not sure if i + 1 correct - // pipe(command->argv[i+1]); - } - if (strpbrk(command->argv[i], ">>")!= NULL) - { - append(command->argv[i-1], command->argv[i+1]); - } + for (int i = 0; i < command->argc; i++) + { + if ((command->argv[i][0] == '>') && (command->argv[i][1] == '>')) + printf(">> was found.\n"); + // ParseInput(inputString, command, ">>"); + if (command->argv[i][0] == '<') + printf("< was found.\n"); + // ParseInput(inputString, command, "<"); + if (command->argv[i][0] == '>' && command->argv[i][1] != '>') + printf("> was found.\n"); + // ParseInput(inputString, command, ">"); + if (command->argv[i][0] == '|') + printf("| was found.\n"); + // ParseInput(inputString, command, "|"); + // else + // ParseInput(inputString, command, " "); } + return; +} + +// Count number of appearances of a symbol in a CommandStruct +int CountSymbol(CommandStruct* command, char symbol) +{ + int count = 0; + for (int i = 0; i < command->argc; i++) + if (command->argv[i][0] == symbol) + count++; + return count; +} + +void ioRedirection(CommandStruct* command) +{ + for (int i = 0; i argv[i], ">>")!= NULL)//append + { + append(command->argv[i-1], command->argv[i+1]); + } + else if (command->argv[i][0] =='<')//input + { + input(command->argv[i+1]); + } + else if (strchr(command->argv[i],'|')!= NULL)//pipe + { + //ExecPipe(); + } + else if (command->argv[i][0] == '>')//output + { + output(command->argv[i+1]); + } + else{} + //exit + } } void output(char *command){ int newfd; - if (newfd = open(command, O_CREAT | O_TRUNC | O_WRONLY, 0644) < 0) + if (newfd = open(command, O_CREAT | O_CREAT, 0666) < 0) { perror(command); exit(1); @@ -141,7 +157,7 @@ void output(char *command){ void input(char *command) { int newfd; - if (newfd = open(command, O_RDONLY) < 0) + if (newfd = open(command, O_RDONLY | O_CREAT) < 0) { perror(command); exit(1); @@ -149,17 +165,53 @@ void input(char *command) dup2(newfd,0); } -void ExecPipe() +// Splits a parent process into separate children processes +int ExecPipe(CommandStruct* commandParent, CommandStruct* commandChild, int* pipefd) { - ; + char buffer[1024]; + int forkPID; + int pipeAmount = CountSymbol(commandParent, '|'); + int pipeLocation = 0; + int startArgc = 0; + int endArgc = commandParent->argc; + pipe(pipefd); + for (int i = 0; i < pipeAmount; i++) + { + pipeLocation = CheckSymbol(commandParent, '|', startArgc); + endArgc = pipeLocation; + CopyCommandStruct(commandParent, commandChild, startArgc, endArgc); + forkPID = fork(); + if (forkPID == 0) + return forkPID; + close(pipefd[0]); + close(pipefd[1]); + wait(&forkPID); + startArgc = pipeLocation + 1; + ResetCommandStruct(commandChild); // Clean command + pipe(pipefd); + } + endArgc = commandParent->argc; + forkPID = fork(); + CopyCommandStruct(commandParent, commandChild, startArgc, endArgc); + if (forkPID == 0) + return forkPID; + close(pipefd[1]); + wait(&forkPID); + while (read(pipefd[0], buffer, sizeof(buffer)) != 0) + printf("%s", buffer); + close(pipefd[0]); + ResetCommandStruct(commandChild); // Clean command + return 1; } -void append(char *input, char *file) +void append(char* input, char* fileName) { - FILE *fp; - fp = fopen(file, "a+"); - fputs(input, fp); - fclose(fp); + char buffer[4]; + int fd = open(fileName, O_APPEND | O_CREAT); + + // fp = fopen(file, "a+"); + // fputs(input, fp); + // fclose(fp); } // check command standard input diff --git a/src/Pish.c b/src/Pish.c index a4d370d..c65d5d9 100644 --- a/src/Pish.c +++ b/src/Pish.c @@ -1,43 +1,92 @@ #include +#include +#include #include #include #include #include #include +#include "Common.h" #include "Integrated.h" #include "Pish.h" // Main function for Pish program void Pish(void) { - CommandStruct commandObject = {"", 0}; - CommandStruct* command = &commandObject; + CommandStruct commandParentObject = {"", 0}; + CommandStruct commandChildObject = {"", 0}; + CommandStruct* commandParent = &commandParentObject; + CommandStruct* commandChild = &commandChildObject; char inputString[1000]; // Max 1000 characters int forkPID; - ReadPishrc(command, inputString); + signal(SIGINT, SIG_IGN); + signal(SIGQUIT, SIG_IGN); + signal(SIGTERM, SIG_IGN); + ReadPishrc(commandParent, commandChild, inputString); while (1) { - ResetCommandStruct(command); // Clean command + int pipefd[2]; + ResetCommandStruct(commandParent); // Clean command strcpy(inputString, ""); // Clean inputString GetInput(inputString); - ParseInput(inputString, command); - if (IntegratedCheck(command)) + if (strcmp(inputString, "") == 0) + continue; + SplitInput(inputString, commandParent); + if (IntegratedCheck(commandParent)) continue; - forkPID = fork(); + forkPID = ExecPipe(commandParent, commandChild, pipefd); + // CheckRedirection(inputString, command); + // CheckRedirection(command); + // ioRedirection(command); // Child if (forkPID == 0) - { - // This is the child process - // Setup the child's process environment here - // E.g., where is standard I/O, how to handle signals? - // execve() is recommended, execvpe() may be better - execvp(command->argv[0], command->argv); - // exec does not return if it succeeds - printf("ERROR: Could not execute %s\n", inputString); - exit(1); - } + RunChild(commandChild, pipefd); // Parent // This is the parent process; Wait for the child to finish - wait(&forkPID); } } + +// Reads ~/.pishrc and runs each command in the file +void ReadPishrc(CommandStruct *commandParent, CommandStruct *commandChild, char *inputString) +{ + char buffer[1]; + int pipefd[2]; + int forkPID; + int *argc = &(commandParent->argc); + char* pishLocation = GetHomeDir(); + strcat(pishLocation, "/.pishrc"); + int fd = open(pishLocation, O_RDONLY | O_CREAT, 0644); + assert(fd > -1); + while (read(fd, buffer, 1) > 0) + { + if (buffer[0] == '\n') + { + SplitInput(inputString, commandParent); + if (IntegratedCheck(commandParent)) + continue; + forkPID = ExecPipe(commandParent, commandChild, pipefd); + if (forkPID == 0) + RunChild(commandChild, pipefd); + strcpy(inputString, ""); + ResetCommandStruct(commandParent); + continue; + } + strcat(inputString, buffer); + } + assert(close(fd) >= 0); +} + +// Run a child process +void RunChild(CommandStruct* commandChild, int* pipefd) +{ + close(pipefd[0]); + dup2(pipefd[1], 1); + close(pipefd[1]); + // execve() is recommended, execvpe() may be better + CheckRedirection(commandChild); + // ioRedirection(commandChild); + execvp(commandChild->argv[0], commandChild->argv); + // exec does not return if it succeeds + printf("ERROR: Could not execute %s\n", commandChild->argv[0]); + exit(1); +}