mshell/src/line_parce.c

303 lines
7.6 KiB
C

#include "../include/shell.h"
#include "../include/utils.h"
#include "../include/input.h"
/**
* @brief Extracts command and its arguments from line
*
* @param line
* @param args
*/
cmds_p *process_line(char *line)
{
int line_size = strlen(line);
if (line_size < 1)
return NULL;
char *tmp = strdup(line), *free_tmp = tmp;
cmds_p *coms = new_cmd();
cmds_p *curr_cmd = coms;
cmd_pipe *curr_pipe = curr_cmd->pipe;
curr_pipe->pipefd[0] = STDIN_FILENO;
for (int i = 0; i < line_size; i++)
{
if (line[i] == '"')
{
tmp++;
i++;
int j = i;
for (; j < line_size; j++)
if (line[j] == '"')
{
free_tmp[j] = '\0';
append_to_str_arr(&(curr_pipe->args), &curr_pipe->args_am, trim_string(tmp, false));
tmp += strlen(curr_pipe->args[curr_pipe->args_am - 1]) + 1;
break;
}
if (j >= line_size)
{
char *ap_line = read_line();
line = realloc(line, strlen(line) + strlen(ap_line) + 1);
line = strcat(line, ap_line);
line_size = strlen(line);
free(ap_line);
i--;
continue;
}
i = j;
if (tmp[0] == ' ')
{
tmp++;
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_pipe->args), &curr_pipe->args_am, trim_string(tmp, false));
tmp += strlen(curr_pipe->args[curr_pipe->args_am - 1]) + 1;
}
else
tmp++;
curr_pipe->args = realloc(curr_pipe->args, sizeof(char *) * (curr_pipe->args_am + 1));
curr_pipe->args[curr_pipe->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;
}
if (tmp[0] == ' ')
{
tmp++;
i++;
}
if (curr_pipe->args[0] != NULL)
{
if (strcmp(curr_pipe->args[0], "!") == 0)
{
curr_cmd->stat.invert = true;
}
}
cmds_p *next = new_cmd();
curr_cmd->next = next;
curr_cmd = curr_cmd->next;
curr_pipe = curr_cmd->pipe;
}
else if (line[i] == '|')
{
if (line[i - 1] != ' ')
{
append_to_str_arr(&(curr_pipe->args), &curr_pipe->args_am, trim_string(tmp, false));
tmp += strlen(curr_pipe->args[curr_pipe->args_am - 1]) + 1;
}
else
tmp++;
curr_pipe->args = realloc(curr_pipe->args, sizeof(char *) * (curr_pipe->args_am + 1));
curr_pipe->args[curr_pipe->args_am] = NULL;
if (tmp[0] == ' ')
{
tmp++;
i++;
}
if (curr_pipe->args[0] != NULL)
{
if (strcmp(curr_pipe->args[0], "!") == 0)
{
curr_cmd->stat.invert = true;
}
}
cmd_pipe *next = new_cmd_pipe();
curr_pipe->next = next;
curr_cmd->pipes_am++;
curr_pipe = curr_pipe->next;
}
else if (line[i] == '>' || line[i] == '<')
{
int flags = 0;
int f = 0;
if (line[i] == '>' && line[i + 1] == '>')
{
flags = O_CREAT | O_APPEND | O_WRONLY;
i++;
tmp++;
f = 0;
}
else if (line[i] == '>')
{
flags = O_CREAT | O_TRUNC | O_WRONLY;
f = 0;
}
else if (line[i] == '<' && line[i + 1] == '>')
{
flags = O_CREAT | O_RDWR;
i++;
tmp++;
f = 1;
}
else if (line[i] == '<')
{
flags = O_RDONLY;
f = 2;
}
i++;
tmp++;
if (line[i] == ' ')
{
i++;
tmp++;
}
int j = i;
for (; j < line_size; j++)
if (line[j] == ' ' || line[j] == '|' || line[j] == '&' || line[j] == ';')
break;
free_tmp[j] = '\0';
if (tmp[0] == '"')
tmp++;
if (free_tmp[j - 1] == '"')
free_tmp[j - 1] = '\0';
int ffd;
if ((ffd = open(tmp, flags)) < 0)
{
perror("file redirection: open");
return NULL;
}
if (f == 0)
curr_pipe->pipefd[1] = ffd;
else if (f == 1)
for (int k = 0; k < 2; k++)
curr_pipe->pipefd[k] = ffd;
else if (f == 2)
curr_pipe->pipefd[0] = ffd;
tmp += j - i + 1;
i = j;
}
else if (line[i] == ' ')
{
free_tmp[i] = '\0';
char *ap_string = trim_string(tmp, false), **exp = calloc(0, sizeof(char *));
int sz = expand_wildcatrd(&exp, ap_string);
for (int l = 0; l < sz; l++)
append_to_str_arr(&(curr_pipe->args), &curr_pipe->args_am, exp[l]);
tmp += strlen(ap_string) + 1;
}
else if (line[i] == '#')
{
break;
}
}
if (tmp[0] != '\0' && tmp[0] != '#')
{
if (tmp[strlen(tmp) - 1] != '"')
{
char *ap_string = trim_string(tmp, false), **exp = calloc(0, sizeof(char *));
int sz = expand_wildcatrd(&exp, ap_string);
for (int l = 0; l < sz; l++)
append_to_str_arr(&(curr_pipe->args), &curr_pipe->args_am, exp[l]);
}
else
append_to_str_arr(&curr_pipe->args, &curr_pipe->args_am, trim_string(tmp, false));
}
if (curr_pipe->args[0] != NULL)
{
if (strcmp(curr_pipe->args[0], "!") == 0)
{
curr_cmd->stat.invert = true;
}
}
free(free_tmp);
if (curr_pipe->args[curr_pipe->args_am] != NULL)
{
curr_pipe->args = realloc(curr_pipe->args, sizeof(char *) * (curr_pipe->args_am + 1));
curr_pipe->args[curr_pipe->args_am] = NULL;
}
if (curr_pipe->pipefd[1] < 0)
curr_pipe->pipefd[1] = STDOUT_FILENO;
return coms;
}
/**
* @brief Expands wildcard in argument
*
* @param arr
* @param input
* @return int
*/
int expand_wildcatrd(char ***arr, char *input)
{
int size = 0;
if (strchr(input, '*') || strchr(input, '~') || strchr(input, '?'))
{
glob_t globbuf;
int t = glob(input, GLOB_TILDE, NULL, &globbuf);
if (t != 0)
perror("Glob");
for (int j = 0; j < globbuf.gl_pathc; j++)
append_to_str_arr(arr, &size, globbuf.gl_pathv[j]);
}
else
append_to_str_arr(arr, &size, input);
return size;
}