Added semicolon separated sequences execution
This commit is contained in:
parent
d578d08410
commit
9fe0b6a293
@ -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
|
@ -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
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
104
src/shell.c
104
src/shell.c
@ -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;
|
||||||
}
|
}
|
21
src/utils.c
21
src/utils.c
@ -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)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user