From 9fe0b6a2937687c43795c04e06229a1464d942c9 Mon Sep 17 00:00:00 2001 From: Dm1tr1y147 Date: Wed, 15 Jul 2020 13:35:29 +0500 Subject: [PATCH] Added semicolon separated sequences execution --- README.md | 6 ++- include/shell.h | 17 ++++++-- include/utils.h | 2 +- src/keys.c | 5 ++- src/shell.c | 104 ++++++++++++++++++++++++++++++++++++------------ src/utils.c | 21 +++++----- 6 files changed, 113 insertions(+), 42 deletions(-) diff --git a/README.md b/README.md index bd89d23..6d9379d 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,8 @@ Work is still in porgress, buf when you will see a "finished" topic assigned to * Files and commands from `/usr/bin` autocompletion on `Tab` keypress * History of commands and navigation or search through it with `up/down` keys * Username, ip address and current path in prompt before each command input -* Invert return status of command with `!`, separated with space, specified before it +* Show previous command return status in prompt and invert it with `!`, separated with space, specified before it +* Running multiple commands separated by `;` # Builtin commands * `cd`: changes current working directory to the one specified by user. If no arguments provided, shows error. @@ -23,4 +24,5 @@ Work is still in porgress, buf when you will see a "finished" topic assigned to * Replace linux `echo` command with builtin one with support of environmental variables * Environmental variables * `Ctrl+Z` running programm with `fd` -* ~~Getting commands path from system `PATH` environment variable~~ \ No newline at end of file +* ~~Getting commands path from system `PATH` environment variable~~ +* Running multiple commands separated by `&&` and `||` with appropriate logic \ No newline at end of file diff --git a/include/shell.h b/include/shell.h index 0c7b20e..debf36b 100644 --- a/include/shell.h +++ b/include/shell.h @@ -47,12 +47,21 @@ struct status bool invert; }; +typedef enum +{ + NO_SEP, + SEMICOLON_SEP, + AND_SEP, + OR_SEP +} cmd_sep; + typedef struct commands { char **args; struct status stat; struct commands *next; -} * cmds_p; + cmd_sep sep_next; +} cmds_p; typedef struct { @@ -66,10 +75,10 @@ extern t_ term; extern char *builtin[]; // Functions prototypes -int process_line(char *line, cmds_p *coms); +int process_line(char *line, cmds_p **coms); int launch(char **args); void process_command(); -int execute(cmds_p command); +int execute(cmds_p *command); void sig_handler(); @@ -79,6 +88,8 @@ int sh_exec(char **args); char *compose_prompt(); +cmds_p *new_cmd(); + #define BUILTIN_NUM sizeof(builtin) / sizeof(char *) #endif \ No newline at end of file diff --git a/include/utils.h b/include/utils.h index ff9d34a..4a95dbd 100644 --- a/include/utils.h +++ b/include/utils.h @@ -18,7 +18,7 @@ void append_to_pos(char **str, int pos, char ch); void remove_on_pos(char **str, int pos); int sep_string(char *line, char ***toks, char *sep); -char *trim_string(char **str, bool leave_trailing_space); +char *trim_string(char *str, bool leave_trailing_space); void free_str_arr(char **arr); char **slice_array(char **arr, int beg, int end, bool asc); int get_null_term_arr_size(char **arr); diff --git a/src/keys.c b/src/keys.c index e23d079..0129d9c 100644 --- a/src/keys.c +++ b/src/keys.c @@ -268,7 +268,10 @@ void tab_key(int *pos, int *n, char **line) (*line)[*pos] = '\0'; *line = realloc(*line, strlen(*line) + 1); - *line = trim_string(line, true); + char *tmp = trim_string(*line, true); + free(*line); + *line = tmp; + *pos = strlen(*line); *n = *pos; diff --git a/src/shell.c b/src/shell.c index 5814f23..f66be26 100644 --- a/src/shell.c +++ b/src/shell.c @@ -19,17 +19,20 @@ int (*builtin_func[])(char **) = { */ void process_command() { - cmds_p coms = NULL; + cmds_p *coms = NULL; char *prompt = compose_prompt(); print_str(prompt, strlen(prompt)); char *line = read_line(); - line = trim_string(&line, false); + + char *tmp = trim_string(line, false); + free(line); + line = tmp; process_line(line, &coms); - cmds_p curr = coms; + cmds_p *curr = coms; int status = 0; while (curr != NULL) { @@ -57,18 +60,14 @@ void process_command() * @param line * @param args */ -int process_line(char *line, cmds_p *coms) +int process_line(char *line, cmds_p **coms) { char *tmp = strdup(line), *free_tmp = tmp; - int args_am = 0; + int line_size = strlen(line), args_am = 0; - *coms = malloc(sizeof(cmds_p)); - (*coms)->args = malloc(sizeof(char *) * args_am); - (*coms)->stat.s = 0; - (*coms)->stat.invert = false; - (*coms)->next = NULL; + *coms = new_cmd(); - int line_size = strlen(line); + cmds_p *curr_cmd = *coms; for (int i = 0; i < line_size; i++) { @@ -81,9 +80,9 @@ int process_line(char *line, cmds_p *coms) { free_tmp[j] = '\0'; - append_to_str_arr(&((*coms)->args), &args_am, tmp); + append_to_str_arr(&(curr_cmd->args), &args_am, trim_string(tmp, false)); - tmp += strlen((*coms)->args[args_am - 1]) + 1; + tmp += strlen(curr_cmd->args[args_am - 1]) + 1; break; } @@ -101,15 +100,60 @@ int process_line(char *line, cmds_p *coms) i--; continue; } - i += j; + i += j - i; + } + else if (line[i] == ';' || (line[i] == '&' && line[i + 1] == '&') || (line[i] == '|' && line[i + 1] == '|')) + { + free_tmp[i] = '\0'; + if (line[i - 1] != ' ') + { + append_to_str_arr(&(curr_cmd->args), &args_am, trim_string(tmp, false)); + tmp += strlen(curr_cmd->args[args_am - 1]) + 1; + } + else { + tmp++; + } + if (tmp[0] == ' ') + { + tmp++; + i++; + } + + curr_cmd->args = realloc(curr_cmd->args, sizeof(char *) * (args_am + 1)); + curr_cmd->args[args_am] = NULL; + + switch (line[i]) + { + case ';': + curr_cmd->sep_next = SEMICOLON_SEP; + break; + + case '&': + curr_cmd->sep_next = AND_SEP; + i++; + tmp++; + break; + + case '|': + curr_cmd->sep_next = OR_SEP; + i++; + tmp++; + break; + } + + cmds_p *next = new_cmd(); + + curr_cmd->next = next; + curr_cmd = curr_cmd->next; + args_am = 0; } else if (line[i] == ' ') { free_tmp[i] = '\0'; - append_to_str_arr(&((*coms)->args), &args_am, tmp); + append_to_str_arr(&(curr_cmd->args), &args_am, trim_string(tmp, false)); - tmp += strlen((*coms)->args[args_am - 1]) + 1; + tmp += strlen(curr_cmd->args[args_am - 1]) + 1; } else if (line[i] == '#') { @@ -119,20 +163,21 @@ int process_line(char *line, cmds_p *coms) if (tmp[0] != '\0' && tmp[0] != '#') { - append_to_str_arr(&((*coms)->args), &args_am, tmp); + append_to_str_arr(&(curr_cmd->args), &args_am, trim_string(tmp, false)); } - if ((*coms)->args[0] != NULL) + if (curr_cmd->args[0] != NULL) { - if (strcmp((*coms)->args[0], "!") == 0) + if (strcmp(curr_cmd->args[0], "!") == 0) { - (*coms)->stat.invert = true; + curr_cmd->stat.invert = true; } } free(free_tmp); - (*coms)->args[args_am] = NULL; + curr_cmd->args = realloc(curr_cmd->args, sizeof(char *) * (args_am + 1)); + curr_cmd->args[args_am] = NULL; return args_am; } @@ -142,7 +187,7 @@ int process_line(char *line, cmds_p *coms) * @param args * @return int */ -int execute(cmds_p command) +int execute(cmds_p *command) { if (command->args[0] == NULL) return 1; @@ -178,7 +223,7 @@ int launch(char **args) } else if (pid < 0) { - perror("myshell"); + perror("myshell1"); } else do @@ -201,7 +246,7 @@ int sh_cd(char **args) if (args[1] == NULL) chdir(getenv("HOME")); else if (chdir(args[1]) < 0) - perror("myshell"); + perror("myshell2"); return 0; } @@ -233,7 +278,7 @@ int sh_exec(char **args) if (execvp(args[0], args) < 0) { - perror("myshell"); + perror("myshell3"); } exit(EXIT_FAILURE); @@ -321,4 +366,13 @@ char *compose_prompt() prompt = strcat(prompt, "\n% "); return prompt; +} + +cmds_p *new_cmd() +{ + cmds_p *new = malloc(sizeof(cmds_p)); + new->args = calloc(0, sizeof(char *)); + new->stat.s = 0; + new->stat.invert = false; + new->next = NULL; } \ No newline at end of file diff --git a/src/utils.c b/src/utils.c index 360d8df..f02b71e 100644 --- a/src/utils.c +++ b/src/utils.c @@ -77,23 +77,24 @@ int sep_string(char *line, char ***toks, char *sep) * @param str * @return char* */ -char *trim_string(char **str, bool leave_trailing_space) +char *trim_string(char *str, bool leave_trailing_space) { - while ((*str)[0] == ' ') - remove_on_pos(str, 1); + char *tmp = strdup(str); + while (tmp[0] == ' ') + remove_on_pos(&tmp, 1); - for (int i = 1; i < strlen(*str); i++) - if ((*str)[i] == ' ' && (*str)[i - 1] == ' ') + for (int i = 1; i < strlen(tmp); i++) + if (tmp[i] == ' ' && tmp[i - 1] == ' ') { - remove_on_pos(str, i); + remove_on_pos(&tmp, i); i--; } if (!leave_trailing_space) - if ((*str)[strlen(*str) - 1] == ' ' && (*str)[strlen(*str) - 2] == ' ') - remove_on_pos(str, strlen(*str) - 1); + if (tmp[strlen(tmp) - 1] == ' ' && tmp[strlen(tmp) - 2] == ' ') + remove_on_pos(&tmp, strlen(tmp) - 1); - return *str; + return tmp; } /** @@ -149,7 +150,7 @@ int get_null_term_arr_size(char **arr) for (int i = 0; arr[i] != NULL; i++) k++; - return k; + return ++k; } int append_to_str_arr(char ***arr, int *sz, char *str)