#include <stdio.h> #include <string.h> #include <stdlib.h> #include "utils.h" void readCommandLine(char *commandLine) { int i = 0; // Iterating index char c; // Temporary variable for reading characters while (1) { // Iterates through the scanned command line c = getchar(); // Gets the current character if (c == '\n') { // Meeting line break commandLine[i ++] = '\0'; // Sets null character to the end of command line break; // Breaks out of loop since reading ends } else { // Not meeting line break commandLine[i ++] = c; // Appends current character into the command line } } } int parseNoPiping(char *commandLine, char *buf) { int i = 0, j, k; // Iterating indices char *token; // Temporary string for parsing hasInput = 0; // Whether input is redirected hasOutput = 0; // Whether output is redirected inputIndex = 0; // Index of the input redirection character outputIndex = 0; // Index of the output redirection character inputFileName = NULL; // Input file name outputFileName = NULL; // Output file name for (i = 0; commandLine[i]; i ++) { // Iterates through the command line if (commandLine[i] == '<') { // Meets input redirection character if (inputIndex == 0) { // Input redirection never met hasInput = 1; // Sets input to be redirected inputIndex = i; // Sets index of the input redirection character to current index } else { // Input redirection already met fprintf(stderr, "Error: invalid command\n"); // Raises error since there cannot be multiple input redirection return -1; // Skips checking and returns a fail signal } } else if (commandLine[i] == '>' && commandLine[i + 1] == '>') { // Meets output redirection character in append mode if (outputIndex == 0) { // Output redirection never met hasOutput = 2; // Sets output to be redirected in append mode outputIndex = i; // Sets index of the output redirection character to current index i ++; // Skips the next index since two characters are taken } else { // Output redirection already met fprintf(stderr, "Error: invalid command\n"); // Raises error since there cannot be multiple output redirection return -1; // Skips checking and returns a fail signal } } else if (commandLine[i] == '>') { // Meets output redirection character in write mode if (outputIndex == 0) { // Output redirection never met hasOutput = 1; // Sets output to be redirected in write mode outputIndex = i; // Sets index of the output redirection character to current index } else { // Output redirection already met fprintf(stderr, "Error: invalid command\n"); // Raises error since there cannot be multiple output redirection return -1; // Skips checking and returns a fail signal } } } strcpy(buf, commandLine); // Copies to buffer to avoid modifying the command line int inputFlag, outputFlag; // Creates input and output flags if (hasInput != 0 && hasOutput != 0) { // Input and output both redirected if (inputIndex < outputIndex) { // Input redirection before output redirection k = 0; // Iterating index for tokens token = strtok(strchr(buf, '<'), " \t\n"); // Token starting from input redirection while (token != 0) { // Not the last token if (strcmp(token, "<\0") == 0) { // Current token is input redirection character inputFlag = k; // Sets input flag to the current token index } else if (strcmp(token, ">\0") == 0 || strcmp(token, ">>\0") == 0) { // Current token is output redirection character outputFlag = k; // Sets output flag to the current token index } k ++; // Increments the iterating index for tokens token = strtok(0, " \t\n"); // Moves to next token } if (outputFlag - inputFlag != 2 || k - outputFlag != 2) { // Input or output redirection taking 0 or 2+ arguments fprintf(stderr, "Error: invalid command\n"); // Raises error since input and output redirection both take only 1 argument return -1; // Skips checking and returns a fail signal } } else { // Output redirection before input redirection k = 0; // Iterating index for tokens token = strtok(strchr(buf, '>'), " \t\n"); // Token starting from output redirection while (token != 0) { // Not the last token if (strcmp(token, "<\0") == 0) { // Current token is input redirection character inputFlag = k; // Sets input flag to the current token index } else if (strcmp(token, ">\0") == 0 || strcmp(token, ">>\0") == 0) { // Current token is output redirection character outputFlag = k; // Sets output flag to the current token index } k ++; // Increments the iterating index for tokens token = strtok(0, " \t\n"); // Moves to next token } if (inputFlag - outputFlag != 2 || k - inputFlag != 2) { // Output or input redirection taking 0 or 2+ arguments fprintf(stderr, "Error: invalid command\n"); // Raises error since output and input redirection both take only 1 argument return -1; // Skips checking and returns a fail signal } } } else if (hasInput != 0) { // Only input redirected k = 0; // Iterating index for tokens token = strtok(strchr(buf, '<'), " \t\n"); // Token starting from input redirection while (token != 0) { // Not the last token if (strcmp(token, "<\0") == 0) { // Current token is input redirection character inputFlag = k; // Sets input flag to the current token index } k ++; // Increments the iterating index for tokens token = strtok(0, " \t\n"); // Moves to next token } if (k - inputFlag != 2) { // Input redirection taking 0 or 2+ arguments fprintf(stderr, "Error: invalid command\n"); // Raises error since input redirection takes only 1 argument return -1; // Skips checking and returns a fail signal } } else if (hasOutput != 0) { // Only output redirected k = 0; // Iterating index for tokens token = strtok(strchr(buf, '>'), " \t\n"); // Token starting from output redirection while (token != 0) { // Not the last token if (strcmp(token, ">\0") == 0 || strcmp(token, ">>\0") == 0) { // Current token is output redirection character outputFlag = k; // Sets output flag to the current token index } k ++; // Increments the iterating index for tokens token = strtok(0, " \t\n"); // Moves to next token } if (k - outputFlag != 2) { // Output redirection taking 0 or 2+ arguments fprintf(stderr, "Error: invalid command\n"); // Raises error since output redirection takes only 1 arguments return -1; // Skips checking and returns a fail signal } } strcpy(buf, commandLine); // Copies to buffer to avoid modifying the command line if (hasInput == 0 && hasOutput == 0) { // No redirection return updateParsedTokens(parsedTokens, buf, " \t\n", token); // Updates parsed tokens array and returns the number of tokens } if (hasInput != 0 && hasOutput != 0) { // Input and output both redirected j = updateParsedTokens(parsedTokens, buf, " \t\n<>", token); // Updates parsed tokens array and gets the number of tokens if (inputIndex < outputIndex) { // Input redirection before output redirection inputFileName = copyString(parsedTokens[j - 2]); // Copies the second last token to input file name outputFileName = copyString(parsedTokens[j - 1]); // Copies the last token to output file name } else { // Output redirection before input redirection inputFileName = copyString(parsedTokens[j - 1]); // Copies the last token to input file name outputFileName = copyString(parsedTokens[j - 2]); // Copies the second last token to output file name } parsedTokens[j - 2] = NULL; // .. parsedTokens[j - 1] = NULL; // Sets redirection tokens to NULL return j - 2; // Returns the number of tokens excluding redirection } if (hasInput != 0) { // Only input redirected char **inputParsedTokens = malloc(sizeof(char) * MAXLENGTH * MAXLENGTH); // Creates input parsed tokens array j = updateParsedTokens(inputParsedTokens, buf, "<", token); // Updates input parsed tokens array and gets the number of input parsed tokens char *copiedInputParsedTokens = copyString(inputParsedTokens[j - 1]); // Copies the last input parsed token inputFileName = copyString(strtok(copiedInputParsedTokens, " \t\n|>")); // Copies the first token in the last input parsed token to input file name j = updateParsedTokens(parsedTokens, buf, " \t\n", token); // Updates parsed tokens array and gets the number of tokens freeAll("21", inputParsedTokens, copiedInputParsedTokens); // Frees all allocated memory return j; // Returns the number of tokens excluding redirection } if (hasOutput != 0) { // Only output redirected char **outputParsedTokens = malloc(sizeof(char) * MAXLENGTH * MAXLENGTH); // Creates output parsed tokens array if (hasOutput == 1) { // Output redirection in truncate mode j = updateParsedTokens(outputParsedTokens, buf, ">", token); // Updates output parsed tokens array and gets the number of output parsed tokens } else if (hasOutput == 2) { // Output redirection in append mode j = updateParsedTokens(outputParsedTokens, buf, ">>", token); // Updates output parsed tokens array and gets the number of output parsed tokens } char *copiedOutputParsedTokens = copyString(outputParsedTokens[j - 1]); // Copies the last output parsed token outputFileName = copyString(strtok(copiedOutputParsedTokens, " \t\n|<")); // Copies the first token in the last output parsed token to output file name j = updateParsedTokens(parsedTokens, buf, " \t\n", token); // Updates parsed tokens array and gets the nummber of tokens freeAll("21", outputParsedTokens, copiedOutputParsedTokens); // Frees all allocated memory return j; // Returns the number of tokens excluding redirection } return -1; // Returns a fail signal (for completeness of function return) } int checkPipingAndRedirection(char *commandLine) { pipeCount = 0; // Number of pipes hasInput = 0; // Whether input is redirected hasOutput = 0; // Whether output is redirected inputIndex = 0; // Index of the input redirection character outputIndex = 0; // Index of the output redirection character for (int i = 0; commandLine[i]; i ++) { // Traverses through the command line if (commandLine[i] == '|') { // Meets pipe pipeCount ++; // Increments the number of pipes } else if (commandLine[i] == '<') { // Meets input redirection character if (inputIndex == 0) { // Input redirection never met hasInput = 1; // Sets input to be redirected inputIndex = i; // Sets index of the input redirection character to current index } else { // Input redirection already met fprintf(stderr, "Error: invalid command\n"); // Raises error since there cannot be multiple input redirection return -1; // Skips checking and returns a fail signal } } else if (commandLine[i] == '>' && commandLine[i + 1] == '>') { // Meets output redirection character in append mode if (outputIndex == 0) { // Output redirection never met hasOutput = 2; // Sets output to be redirected in append mode outputIndex = i; // Sets index of the output redirection character to current index i ++; // Skips the next index since two characters are taken } else { // Output redirection already met fprintf(stderr, "Error: invalid command\n"); // Raises error since there cannot be multiple output redirection return -1; // Skips checking and returns a fail signal } } else if (commandLine[i] == '>') { // Meets output redirection character in write mode if (outputIndex == 0) { // Output redirection never met hasOutput = 1; // Sets output to be redirected in write mode outputIndex = i; // Sets index of the output redirection character to current index } else { // Output redirection already met fprintf(stderr, "Error: invalid command\n"); // Raises error since there cannot be multiple output redirection return -1; // Skips checking and returns a fail signal } } } return pipeCount; // Returns the number of pipes } int parseByPipe(char *commandLine, char *buf) { int i = 0; // Iterating index strcpy(buf, commandLine); // Copies command line to buffer to avoid modifying the command line char *pipedCommand = strtok(buf, "|"); // First subcommand in the command line while (pipedCommand != 0) { // Not the last subcommand pipedCommands[i ++] = pipedCommand; // Append current subcommand to piiped commands array and increments the iterating index pipedCommand = strtok(0, "|"); // Moves to next subcommand } pipedCommands[i] = NULL; // Terminates piped commands array return i; // Returns the number of subcommands } int updateParsedTokens(char **tokenArray, char *buf, char *delimiter, char *token) { int i = 0; // Iterating index for tokens token = strtok(buf, delimiter); // First token in the command line while (token != 0) { // Not the last token tokenArray[i ++] = token; // Appends current token to parsed tokens array and increments the iterating index token = strtok(0, delimiter); // Moves to next token } tokenArray[i] = NULL; // Terminates parsed tokens array return i; // Returns the number of tokens }