Added semicolon separated sequences execution

This commit is contained in:
Dmitriy Shishkov 2020-07-15 13:35:29 +05:00
parent d578d08410
commit 9fe0b6a293
6 changed files with 113 additions and 42 deletions

View File

@ -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 * Files and commands from `/usr/bin` autocompletion on `Tab` keypress
* History of commands and navigation or search through it with `up/down` keys * 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 * 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 # Builtin commands
* `cd`: changes current working directory to the one specified by user. If no arguments provided, shows error. * `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 * Replace linux `echo` command with builtin one with support of environmental variables
* Environmental variables * Environmental variables
* `Ctrl+Z` running programm with `fd` * `Ctrl+Z` running programm with `fd`
* ~~Getting commands path from system `PATH` environment variable~~ * ~~Getting commands path from system `PATH` environment variable~~
* Running multiple commands separated by `&&` and `||` with appropriate logic

View File

@ -47,12 +47,21 @@ struct status
bool invert; bool invert;
}; };
typedef enum
{
NO_SEP,
SEMICOLON_SEP,
AND_SEP,
OR_SEP
} cmd_sep;
typedef struct commands typedef struct commands
{ {
char **args; char **args;
struct status stat; struct status stat;
struct commands *next; struct commands *next;
} * cmds_p; cmd_sep sep_next;
} cmds_p;
typedef struct typedef struct
{ {
@ -66,10 +75,10 @@ extern t_ term;
extern char *builtin[]; extern char *builtin[];
// Functions prototypes // Functions prototypes
int process_line(char *line, cmds_p *coms); int process_line(char *line, cmds_p **coms);
int launch(char **args); int launch(char **args);
void process_command(); void process_command();
int execute(cmds_p command); int execute(cmds_p *command);
void sig_handler(); void sig_handler();
@ -79,6 +88,8 @@ int sh_exec(char **args);
char *compose_prompt(); char *compose_prompt();
cmds_p *new_cmd();
#define BUILTIN_NUM sizeof(builtin) / sizeof(char *) #define BUILTIN_NUM sizeof(builtin) / sizeof(char *)
#endif #endif

View File

@ -18,7 +18,7 @@
void append_to_pos(char **str, int pos, char ch); void append_to_pos(char **str, int pos, char ch);
void remove_on_pos(char **str, int pos); void remove_on_pos(char **str, int pos);
int sep_string(char *line, char ***toks, char *sep); 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); void free_str_arr(char **arr);
char **slice_array(char **arr, int beg, int end, bool asc); char **slice_array(char **arr, int beg, int end, bool asc);
int get_null_term_arr_size(char **arr); int get_null_term_arr_size(char **arr);

View File

@ -268,7 +268,10 @@ void tab_key(int *pos, int *n, char **line)
(*line)[*pos] = '\0'; (*line)[*pos] = '\0';
*line = realloc(*line, strlen(*line) + 1); *line = realloc(*line, strlen(*line) + 1);
*line = trim_string(line, true); char *tmp = trim_string(*line, true);
free(*line);
*line = tmp;
*pos = strlen(*line); *pos = strlen(*line);
*n = *pos; *n = *pos;

View File

@ -19,17 +19,20 @@ int (*builtin_func[])(char **) = {
*/ */
void process_command() void process_command()
{ {
cmds_p coms = NULL; cmds_p *coms = NULL;
char *prompt = compose_prompt(); char *prompt = compose_prompt();
print_str(prompt, strlen(prompt)); print_str(prompt, strlen(prompt));
char *line = read_line(); char *line = read_line();
line = trim_string(&line, false);
char *tmp = trim_string(line, false);
free(line);
line = tmp;
process_line(line, &coms); process_line(line, &coms);
cmds_p curr = coms; cmds_p *curr = coms;
int status = 0; int status = 0;
while (curr != NULL) while (curr != NULL)
{ {
@ -57,18 +60,14 @@ void process_command()
* @param line * @param line
* @param args * @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; 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 = new_cmd();
(*coms)->args = malloc(sizeof(char *) * args_am);
(*coms)->stat.s = 0;
(*coms)->stat.invert = false;
(*coms)->next = NULL;
int line_size = strlen(line); cmds_p *curr_cmd = *coms;
for (int i = 0; i < line_size; i++) for (int i = 0; i < line_size; i++)
{ {
@ -81,9 +80,9 @@ int process_line(char *line, cmds_p *coms)
{ {
free_tmp[j] = '\0'; 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; break;
} }
@ -101,15 +100,60 @@ int process_line(char *line, cmds_p *coms)
i--; i--;
continue; 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] == ' ') else if (line[i] == ' ')
{ {
free_tmp[i] = '\0'; 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] == '#') else if (line[i] == '#')
{ {
@ -119,20 +163,21 @@ int process_line(char *line, cmds_p *coms)
if (tmp[0] != '\0' && tmp[0] != '#') 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); 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; return args_am;
} }
@ -142,7 +187,7 @@ int process_line(char *line, cmds_p *coms)
* @param args * @param args
* @return int * @return int
*/ */
int execute(cmds_p command) int execute(cmds_p *command)
{ {
if (command->args[0] == NULL) if (command->args[0] == NULL)
return 1; return 1;
@ -178,7 +223,7 @@ int launch(char **args)
} }
else if (pid < 0) else if (pid < 0)
{ {
perror("myshell"); perror("myshell1");
} }
else else
do do
@ -201,7 +246,7 @@ int sh_cd(char **args)
if (args[1] == NULL) if (args[1] == NULL)
chdir(getenv("HOME")); chdir(getenv("HOME"));
else if (chdir(args[1]) < 0) else if (chdir(args[1]) < 0)
perror("myshell"); perror("myshell2");
return 0; return 0;
} }
@ -233,7 +278,7 @@ int sh_exec(char **args)
if (execvp(args[0], args) < 0) if (execvp(args[0], args) < 0)
{ {
perror("myshell"); perror("myshell3");
} }
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
@ -321,4 +366,13 @@ char *compose_prompt()
prompt = strcat(prompt, "\n% "); prompt = strcat(prompt, "\n% ");
return prompt; 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;
} }

View File

@ -77,23 +77,24 @@ int sep_string(char *line, char ***toks, char *sep)
* @param str * @param str
* @return char* * @return char*
*/ */
char *trim_string(char **str, bool leave_trailing_space) char *trim_string(char *str, bool leave_trailing_space)
{ {
while ((*str)[0] == ' ') char *tmp = strdup(str);
remove_on_pos(str, 1); while (tmp[0] == ' ')
remove_on_pos(&tmp, 1);
for (int i = 1; i < strlen(*str); i++) for (int i = 1; i < strlen(tmp); i++)
if ((*str)[i] == ' ' && (*str)[i - 1] == ' ') if (tmp[i] == ' ' && tmp[i - 1] == ' ')
{ {
remove_on_pos(str, i); remove_on_pos(&tmp, i);
i--; i--;
} }
if (!leave_trailing_space) if (!leave_trailing_space)
if ((*str)[strlen(*str) - 1] == ' ' && (*str)[strlen(*str) - 2] == ' ') if (tmp[strlen(tmp) - 1] == ' ' && tmp[strlen(tmp) - 2] == ' ')
remove_on_pos(str, strlen(*str) - 1); 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++) for (int i = 0; arr[i] != NULL; i++)
k++; k++;
return k; return ++k;
} }
int append_to_str_arr(char ***arr, int *sz, char *str) int append_to_str_arr(char ***arr, int *sz, char *str)