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
|
||||
* 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.
|
||||
@ -24,3 +25,4 @@ Work is still in porgress, buf when you will see a "finished" topic assigned to
|
||||
* Environmental variables
|
||||
* `Ctrl+Z` running programm with `fd`
|
||||
* ~~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;
|
||||
};
|
||||
|
||||
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
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
104
src/shell.c
104
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);
|
||||
@ -322,3 +367,12 @@ char *compose_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
|
||||
* @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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user