diff --git a/include/Common.h b/include/Common.h index 25ac07a..7120cfc 100755 --- a/include/Common.h +++ b/include/Common.h @@ -1,11 +1,14 @@ #ifndef COMMON_H #define COMMON_H +const char* GetHomeDir(void); + typedef struct CommandStruct { char* argv[100]; // Max 100 commands int argc; } CommandStruct; +void CopyCommandStruct(CommandStruct* oldCommand, CommandStruct* newCommand, int start, int end); void ResetCommandStruct(CommandStruct* command); #endif \ No newline at end of file diff --git a/include/Integrated.h b/include/Integrated.h index ca25509..b8433e9 100755 --- a/include/Integrated.h +++ b/include/Integrated.h @@ -3,16 +3,16 @@ #include "Common.h" -const char* GetHomeDir(void); void CheckRedirection(CommandStruct* command); +int CheckSymbol(CommandStruct* command, char symbol, int start); 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 SplitInput(char* inputString, CommandStruct* command); -void ParseInput(char* inputString, CommandStruct* command, char *symbol); -void ReadPishrc(CommandStruct* command, char* inputString); +void ParseInput(char* inputString, CommandStruct* command, char* symbol); +void RunChild(CommandStruct* commandChild, int* pipefd); void ioRedirection(CommandStruct* command); #endif diff --git a/include/Pish.h b/include/Pish.h index 9b54a1a..e093cd1 100644 --- a/include/Pish.h +++ b/include/Pish.h @@ -4,5 +4,6 @@ #include "Common.h" void Pish(void); +void ReadPishrc(CommandStruct* commandParent, CommandStruct *commandChild, char* inputString); #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 8e5b051..c39bcfc 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) { @@ -66,35 +57,23 @@ void ParseInput(char *inputString, CommandStruct *command, char *symbol) } } -// Reads ~/.pishrc and runs each command in the file -void ReadPishrc(CommandStruct *command, char *inputString) +// Run child process +void RunChild(CommandStruct* commandChild, int* pipefd) { - 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) - { - 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); - } - assert(close(fd) >= 0); + close(pipefd[0]); + dup2(pipefd[1], 1); + close(pipefd[1]); + // 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(commandChild->argv[0], commandChild->argv); + // exec does not return if it succeeds + printf("ERROR: Could not execute %s\n", commandChild->argv[0]); + exit(1); } + // Splits a string separated by spaces into an array of strings void SplitInput(char *inputString, CommandStruct *command) { @@ -114,6 +93,18 @@ void SplitInput(char *inputString, CommandStruct *command) (*argc)--; } +// Splits a command array into left and right +// void SplitPipe(CommandStruct* commandLeft, CommandStruct* commandRight); + +int CheckSymbol(CommandStruct* command, char symbol, int start) +{ + for (int i = start; i < command->argc; i++) + if (command->argv[i][0] == symbol) + return i; + return -1; +} + + // Checking redirection // TODO: Work on one symbol at a time // inputString may not be useful here, only *command @@ -188,17 +179,45 @@ void input(char *command) dup2(newfd,0); } -void ExecPipe() +int ExecPipe(CommandStruct* commandParent, CommandStruct* commandChild, int* pipefd) { - // ; + char buffer[1024]; + int forkPID; + int pipeLocation = 0; + int startArgc = 0; + int endArgc = commandParent->argc; + while (pipeLocation >= 0) + { + if (pipeLocation > 0) + startArgc = pipeLocation + 1; + pipeLocation = CheckSymbol(commandParent, '|', startArgc); + if (pipeLocation >= 0) + endArgc = pipeLocation - 1; + if (pipeLocation < 0) + endArgc = commandParent->argc; + CopyCommandStruct(commandParent, commandChild, startArgc, endArgc); + pipe(pipefd); + forkPID = fork(); + if (forkPID == 0) + return forkPID; + if (forkPID != 0) + wait(&forkPID); + close(pipefd[1]); + while (read(pipefd[0], buffer, sizeof(buffer)) != 0) + printf("%s", buffer); + 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 477fbf3..fa4f055 100644 --- a/src/Pish.c +++ b/src/Pish.c @@ -1,46 +1,80 @@ #include +#include #include #include #include #include #include +#include "Common.h" #include "Integrated.h" #include "Pish.h" +// Example command: ps aux | grep 'Z' +// Pipe left: [ps aux] +// argv: [ps, aux] +// Pipe right: [grep 'Z'] +// argv: [grep, 'Z'] + +// check for first pipe, split into before and after pipe, +// connect left and right execs + // 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); + ReadPishrc(commandParent, commandChild, inputString); while (1) { - ResetCommandStruct(command); // Clean command + int pipefd[2]; + ResetCommandStruct(commandParent); // Clean command strcpy(inputString, ""); // Clean inputString GetInput(inputString); - SplitInput(inputString, command); - if (IntegratedCheck(command)) + SplitInput(inputString, commandParent); + if (IntegratedCheck(commandParent)) continue; + forkPID = ExecPipe(commandParent, commandChild, pipefd); // CheckRedirection(inputString, command); - CheckRedirection(command); + // CheckRedirection(command); // ioRedirection(command); - forkPID = fork(); // 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); + 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); +} \ No newline at end of file