#include <stdlib.h> #include <stdio.h> #include <string.h> #include <ctype.h> #include "dshlib.h" /* * build_cmd_list * cmd_line: the command line from the user * clist *: pointer to clist structure to be populated * * This function builds the command_list_t structure passed by the caller * It does this by first splitting the cmd_line into commands by spltting * the string based on any pipe characters '|'. It then traverses each * command. For each command (a substring of cmd_line), it then parses * that command by taking the first token as the executable name, and * then the remaining tokens as the arguments. * * NOTE your implementation should be able to handle properly removing * leading and trailing spaces! * * errors returned: * * OK: No Error * ERR_TOO_MANY_COMMANDS: There is a limit of CMD_MAX (see dshlib.h) * commands. * ERR_CMD_OR_ARGS_TOO_BIG: One of the commands provided by the user * was larger than allowed, either the * executable name, or the arg string. * * Standard Library Functions You Might Want To Consider Using * memset(), strcmp(), strcpy(), strtok(), strlen(), strchr() */ int build_cmd_list(char *cmd_line, command_list_t *clist) { if (cmd_line == NULL) { return ERR_CMD_OR_ARGS_TOO_BIG; //I lowkey don't know what other error to put } char *original_line = strdup(cmd_line); //So we duplicate so I can then trimm it down if (original_line == NULL) { return ERR_CMD_OR_ARGS_TOO_BIG; } char *trimmed_line = original_line; // Use another pointer for trimming // Trim leading spaces while (*trimmed_line == ' ') { trimmed_line++; } // Trim trailing spaces size_t len = strlen(trimmed_line); while (len > 0 && trimmed_line[len - 1] == ' ') { trimmed_line[--len] = '\0'; } int command_count = 0; char *saveptr1, *saveptr2; char *command = strtok_r(trimmed_line, PIPE_STRING, &saveptr1); //This is so I can reenter the string to reuse it again so strtok_r would be easier while (command != NULL && command_count < CMD_MAX) { //checks if over max and still variables memset(&clist->commands[command_count], 0, sizeof(command_t)); // Parse the command and its arguments char *command_and_arguments = strtok_r(command, " ", &saveptr2); if (command_and_arguments != NULL) { if (strlen(command_and_arguments) >= EXE_MAX) { free(original_line); return ERR_CMD_OR_ARGS_TOO_BIG; } strcpy(clist->commands[command_count].exe, command_and_arguments); char *arg = strtok_r(NULL, " ", &saveptr2); //Checks argument by space //Space string thingy did not work while (arg != NULL) { if (strlen(clist->commands[command_count].args) + strlen(arg) + 1 >= ARG_MAX) { free(original_line); return ERR_CMD_OR_ARGS_TOO_BIG; } if (strlen(clist->commands[command_count].args) > 0) { strcat(clist->commands[command_count].args, " "); } strcat(clist->commands[command_count].args, arg); arg = strtok_r(NULL, " ", &saveptr2); //increment } } command_count++; command = strtok_r(NULL, PIPE_STRING, &saveptr1); // Get the next command } if (command != NULL) {// If it's empty it breaks, if it somehow breaks and not empty //It does not work free(original_line); return ERR_TOO_MANY_COMMANDS; } clist->num = command_count; free(original_line); // Free the original pointer, not the modified one return OK; }