From 68411d3e3491f721ffefae770a6916e5712afccf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Gendre?= <seb@k-7.ch> Date: Mon, 18 May 2020 23:36:41 +0200 Subject: [PATCH] Start to implement the pipeline mechanism with a chained list of cmd_t --- src/command.c | 95 +++++++++++++++++++++++++++++++++++++++++++++------ src/command.h | 33 ++++++++++++++---- src/shell.c | 9 ++--- 3 files changed, 115 insertions(+), 22 deletions(-) diff --git a/src/command.c b/src/command.c index ee4984a..bd5bf4e 100644 --- a/src/command.c +++ b/src/command.c @@ -3,10 +3,22 @@ #include "command.h" -int command_from_str(char *str, cmd_t *cmd) { +cmd_t *command_from_str(char *str) { - // Stor next command argument, used in the do…while loop + char *str_copy = malloc((strlen(str)+1)*sizeof(char)); + // Generate the command + cmd_t *cmd = malloc(sizeof(cmd_t)); + // Store next command argument, used in the do…while loop char* next_arg; + + // Work with a copy of the given str + strcpy(str_copy, str); + + // If malloc didn't work + if (cmd == NULL) { + perror("Malloc error for new command"); + return (cmd_t *)NULL; + } // Initialize a simple command (empty, simple, foreground) cmd->type = JOB; @@ -19,10 +31,10 @@ int command_from_str(char *str, cmd_t *cmd) { if (cmd->argc == 0) { // Extract the commmand name - next_arg = strtok(str, DELIMITERS); + next_arg = strtok(str_copy, ARGS_DELIMITERS); } else { // Get the next argument - next_arg = strtok(NULL, DELIMITERS); + next_arg = strtok(NULL, ARGS_DELIMITERS); } // Extend the cmd->argv array with a new char pointer @@ -47,22 +59,83 @@ int command_from_str(char *str, cmd_t *cmd) { } else { cmd->type = JOB; } - - return 0; + + return cmd; +} + + +/* Parse a string to get a pipeline of commands */ +cmd_t *command_pipeline_from_str(char *str){ + char **commands = NULL; + char *next_command = NULL; + int commands_count = 0; + cmd_t *previous_command = NULL; + cmd_t *first_command = NULL; + + // Cut str into a list of commands string + do { + if (commands_count == 0) { + // Extract the first command + next_command = strtok(str, COMMAND_PIPE_DELIMITER); + } else { + // Get the next command + next_command = strtok(NULL, COMMAND_PIPE_DELIMITER); + } + + // Extend the command list to add a new command + commands = realloc(commands, (commands_count+1)*sizeof(char *)); + if( commands == NULL) { + // In case the reallocation didn't work + die_errno("parse_command::realloc"); + } + + // Store the next command + commands[commands_count] = next_command; + + if (next_command != NULL) { + // A now command has been added + commands_count += 1; + } + } while (next_command != NULL); + + // For each command string, create a command struct + for (int i = 0; i < commands_count; ++i) { + if (previous_command == NULL) { + first_command = command_from_str(commands[i]); + } else { + previous_command->next = command_from_str(commands[i]); + } + } + + return first_command; } + // Dispose the commande void command_dispose(cmd_t *cmd) { // Free all the command arguments str inside argv - for (int i = 0; i < cmd->argc; ++i) { - free(cmd->argv[i]); - } - // Then, finally, free argv + /* for (int i = 0; i < cmd->argc; ++i) { */ + /* free(cmd->argv[i]); */ + /* } */ + // Free argv free(cmd->argv); + // Then, finally, free the command + free(cmd); +} + + +/* Fee a pipeline of command from the given command */ +void command_free_pipeline(cmd_t *cmd) { + if (cmd->next != NULL) { + command_free_pipeline(cmd->next); + } else { + command_dispose(cmd); + } } + // Execute the commande -int command_exec(cmd_t *cmd) { +int command_pipeline_exec(cmd_t *cmd) { switch (cmd->type) { case BUILTIN: { return builtin_exec_builtin_command(cmd->argc, cmd->argv); diff --git a/src/command.h b/src/command.h index c10254e..e8c7dac 100644 --- a/src/command.h +++ b/src/command.h @@ -13,7 +13,8 @@ #include "jobs.h" // Chars used to separate atoms of a command -#define DELIMITERS " \t" +#define ARGS_DELIMITERS " \t" +#define COMMAND_PIPE_DELIMITER "|" // Command types enum command_type {BUILTIN, JOB, PIZZA}; @@ -21,22 +22,33 @@ enum command_type {BUILTIN, JOB, PIZZA}; // A full user command typedef struct cmd cmd_t; struct cmd { - enum command_type type; // Command type + enum command_type type; // Command type char** argv; // The command arguments int argc; // Number of command arguments bool foreground; // Should the command be run in foreground or background (might not be relevant for your TP depending on TP version) + cmd_t *next; // Pointer to the next command, in case of pipe }; -/* Parse a user input to get a command +/* Parse a string to get one command * * Parameters -* - user_input: A string containing the full command. IT WILL BE MODIFIED BY THE FUNCTION. +* - str: A string containing the full command. IT WILL BE MODIFIED BY THE FUNCTION. * - cmd: Command updated from user input string (i.e. command input). MUST BE DISPOSED SEE FUNCTION dispose_command * * Return: -* -1 in case of error otherwise 0. +* A pointer to the new command, NULL in case of error */ -int command_from_str(char *str, cmd_t *cmd); +cmd_t *command_from_str(char *str); + +/* Parse a string to get a pipeline of commands +* +* Parameters +* - user_input: A string containing the full command. IT WILL BE MODIFIED BY THE FUNCTION. +* +* Return: +* The pointer to the first command, NULL in case of error +*/ +cmd_t *command_pipeline_from_str(char *str); /* Dispose of the command, which free some allocated memory @@ -47,6 +59,13 @@ int command_from_str(char *str, cmd_t *cmd); */ void command_dispose(cmd_t *cmd); +/* Fee a pipeline of command from the given command + * + * Parameters: + * - cmd: The command start command of the pipeline to free +*/ +void command_free_pipeline(cmd_t *cmd); + /* Execute a given command as job or as builtin * * Parameters: @@ -55,7 +74,7 @@ void command_dispose(cmd_t *cmd); * Return: * - The command return code, 0 is success */ -int command_exec(cmd_t *cmd); +int command_pipeline_exec(cmd_t *cmd); #endif /* COMMAND_H */ diff --git a/src/shell.c b/src/shell.c index 738ab4a..79d4bc8 100644 --- a/src/shell.c +++ b/src/shell.c @@ -10,15 +10,16 @@ int main(int argc, char *argv[]) { - char * user_input; - cmd_t command; + char *user_input; + cmd_t *command_p; user_input = calloc(LIMIT_USER_INPUT_MAX_LENGTH, sizeof(char)); while(1){ interface_ask_user_input(user_input); - command_from_str(user_input, &command); - command_exec(&command); + command_p = command_pipeline_from_str(user_input); + command_pipeline_exec(command_p); + command_free_pipeline(command_p); } return 0; } -- GitLab