Compare commits
No commits in common. "2a908210a1717f20d152de1353322f696ec6497b" and "86ecaef72dcee182868377298bfeecbf366c5361" have entirely different histories.
2a908210a1
...
86ecaef72d
1 changed files with 89 additions and 412 deletions
501
main.c
501
main.c
|
|
@ -6,10 +6,8 @@
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <setjmp.h>
|
#include <setjmp.h>
|
||||||
#include <ctype.h>
|
|
||||||
|
|
||||||
constexpr size_t max_length = 1024;
|
constexpr size_t max_lenght = 1024;
|
||||||
constexpr size_t max_env_var_lenght = 256;
|
|
||||||
const char* token_separators = " \t\n\r";
|
const char* token_separators = " \t\n\r";
|
||||||
|
|
||||||
static sigjmp_buf restart_jmp_buf;
|
static sigjmp_buf restart_jmp_buf;
|
||||||
|
|
@ -99,12 +97,12 @@ struct pipeline
|
||||||
struct command* cmds[];
|
struct command* cmds[];
|
||||||
};
|
};
|
||||||
|
|
||||||
void* parser_memory[max_length] = {0};
|
void* parser_memory[max_lenght] = {0};
|
||||||
size_t parser_memory_index = 0;
|
size_t parser_memory_index = 0;
|
||||||
void parser_allocated(void* ptr)
|
void parser_allocated(void* ptr)
|
||||||
{
|
{
|
||||||
parser_memory[parser_memory_index] = ptr;
|
parser_memory[parser_memory_index] = ptr;
|
||||||
if(parser_memory_index == max_length)
|
if(parser_memory_index == max_lenght)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Not enough memory for parser: Memory will leak!");
|
fprintf(stderr, "Not enough memory for parser: Memory will leak!");
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
@ -112,234 +110,30 @@ void parser_allocated(void* ptr)
|
||||||
parser_memory_index++;
|
parser_memory_index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* parser_realloc(void* ptr, size_t size)
|
|
||||||
{
|
|
||||||
size_t index;
|
|
||||||
for(index = 0; index < parser_memory_index; index++)
|
|
||||||
{
|
|
||||||
if(parser_memory[index] == ptr)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ptr = realloc(ptr, size);
|
|
||||||
if (!ptr)
|
|
||||||
{
|
|
||||||
perror("realloc failed");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
parser_memory[index] = ptr;
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void parser_free()
|
void parser_free()
|
||||||
{
|
{
|
||||||
for(size_t i = 0; i < parser_memory_index; i++)
|
for(size_t i = 0; i < parser_memory_index; i++)
|
||||||
{
|
{
|
||||||
free(parser_memory[i]);
|
free(parser_memory[i]);
|
||||||
}
|
}
|
||||||
memset(parser_memory, 0, max_length);
|
memset(parser_memory, 0, max_lenght);
|
||||||
parser_memory_index = 0;
|
parser_memory_index = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* expand_variable(const char* name)
|
/*
|
||||||
|
* For internal use. Returns the next non-empty token according in *line,
|
||||||
|
* splitting on characters in TOKEN_SEP. Returns NULL if no token remains.
|
||||||
|
* Updates line to point to remainder after removal of the token. Modifies the
|
||||||
|
* string *line.
|
||||||
|
*/
|
||||||
|
char* next_non_empty(char **line)
|
||||||
{
|
{
|
||||||
char* val = getenv(name);
|
char *tok;
|
||||||
char* ret = val ? strdup(val) : strdup("");
|
|
||||||
parser_allocated(ret);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void append_char(char** buf, size_t* len, size_t* cap, char c)
|
/* Consume empty tokens. */
|
||||||
{
|
while ((tok = strsep(line, token_separators)) && !*tok);
|
||||||
if (*len + 1 >= *cap)
|
|
||||||
{
|
|
||||||
*cap *= 2;
|
|
||||||
*buf = parser_realloc(*buf, *cap);
|
|
||||||
}
|
|
||||||
(*buf)[(*len)++] = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void append_str(char** buf, size_t* len, size_t* cap, const char* s)
|
return tok;
|
||||||
{
|
|
||||||
while (*s)
|
|
||||||
append_char(buf, len, cap, *s++);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct pipeline* parse_pipeline(char *str);
|
|
||||||
int execute_pipeline(struct pipeline* pl, int capture, char** out);
|
|
||||||
|
|
||||||
static char* run_subcommand(const char* cmd)
|
|
||||||
{
|
|
||||||
struct pipeline* pl = parse_pipeline((char*)cmd);
|
|
||||||
|
|
||||||
char* output = NULL;
|
|
||||||
execute_pipeline(pl, 1, &output);
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
char* parse_token(char** input)
|
|
||||||
{
|
|
||||||
char* p = *input;
|
|
||||||
|
|
||||||
while (*p && isspace(*p))
|
|
||||||
p++;
|
|
||||||
|
|
||||||
if (!*p)
|
|
||||||
{
|
|
||||||
*input = p;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t cap = 64;
|
|
||||||
size_t len = 0;
|
|
||||||
char* buf = malloc(cap);
|
|
||||||
if (!buf)
|
|
||||||
{
|
|
||||||
perror("malloc");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int in_single = 0;
|
|
||||||
int in_double = 0;
|
|
||||||
|
|
||||||
while (*p)
|
|
||||||
{
|
|
||||||
if (!in_single && !in_double && isspace(*p))
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (!in_double && *p == '\'')
|
|
||||||
{
|
|
||||||
in_single = !in_single;
|
|
||||||
p++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!in_single && *p == '"')
|
|
||||||
{
|
|
||||||
in_double = !in_double;
|
|
||||||
p++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!in_single && *p == '\\')
|
|
||||||
{
|
|
||||||
p++;
|
|
||||||
if (*p)
|
|
||||||
append_char(&buf, &len, &cap, *p++);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!in_single && *p == '$')
|
|
||||||
{
|
|
||||||
p++;
|
|
||||||
|
|
||||||
if (*p == '(')
|
|
||||||
{
|
|
||||||
p++;
|
|
||||||
size_t cap2 = 256;
|
|
||||||
size_t len2 = 0;
|
|
||||||
char* cmd = malloc(cap2);
|
|
||||||
if (!cmd) { perror("malloc"); exit(1); }
|
|
||||||
|
|
||||||
int depth = 1;
|
|
||||||
int in_single2 = 0;
|
|
||||||
int in_double2 = 0;
|
|
||||||
|
|
||||||
while (*p && depth > 0)
|
|
||||||
{
|
|
||||||
if (!in_double2 && *p == '\'')
|
|
||||||
{
|
|
||||||
in_single2 = !in_single2;
|
|
||||||
}
|
|
||||||
else if (!in_single2 && *p == '"')
|
|
||||||
{
|
|
||||||
in_double2 = !in_double2;
|
|
||||||
}
|
|
||||||
else if (!in_single2 && !in_double2)
|
|
||||||
{
|
|
||||||
if (*p == '(') depth++;
|
|
||||||
else if (*p == ')') depth--;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (depth > 0)
|
|
||||||
append_char(&cmd, &len2, &cap2, *p);
|
|
||||||
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (depth != 0)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "syntax error: unclosed $( )\n");
|
|
||||||
free(cmd);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd[len2] = '\0';
|
|
||||||
|
|
||||||
char* out = run_subcommand(cmd);
|
|
||||||
append_str(&buf, &len, &cap, out);
|
|
||||||
|
|
||||||
free(cmd);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*p == '{')
|
|
||||||
{
|
|
||||||
p++;
|
|
||||||
char name[max_env_var_lenght];
|
|
||||||
int i = 0;
|
|
||||||
while (*p && *p != '}')
|
|
||||||
name[i++] = *p++;
|
|
||||||
name[i] = '\0';
|
|
||||||
if (*p == '}') p++;
|
|
||||||
char* val = expand_variable(name);
|
|
||||||
append_str(&buf, &len, &cap, val);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
char name[max_env_var_lenght];
|
|
||||||
int i = 0;
|
|
||||||
while (*p && (isalnum(*p) || *p == '_'))
|
|
||||||
name[i++] = *p++;
|
|
||||||
name[i] = '\0';
|
|
||||||
|
|
||||||
char* val = expand_variable(name);
|
|
||||||
append_str(&buf, &len, &cap, val);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!in_single && *p == '`')
|
|
||||||
{
|
|
||||||
p++;
|
|
||||||
char cmd[max_length];
|
|
||||||
int i = 0;
|
|
||||||
while (*p && *p != '`')
|
|
||||||
cmd[i++] = *p++;
|
|
||||||
if (*p == '`') p++;
|
|
||||||
cmd[i] = '\0';
|
|
||||||
char* out = run_subcommand(cmd);
|
|
||||||
append_str(&buf, &len, &cap, out);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
append_char(&buf, &len, &cap, *p++);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (in_single || in_double)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "syntax error: unclosed quote\n");
|
|
||||||
free(buf);
|
|
||||||
*input = p;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
buf[len] = '\0';
|
|
||||||
parser_allocated(buf);
|
|
||||||
|
|
||||||
*input = p;
|
|
||||||
return buf;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -349,7 +143,7 @@ char* parse_token(char** input)
|
||||||
struct command* parse_command(char* str)
|
struct command* parse_command(char* str)
|
||||||
{
|
{
|
||||||
/* Copy the input line in case the caller wants it later. */
|
/* Copy the input line in case the caller wants it later. */
|
||||||
char* copy = strndup(str, max_length);
|
char* copy = strndup(str, max_lenght);
|
||||||
parser_allocated(copy);
|
parser_allocated(copy);
|
||||||
char* token;
|
char* token;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
@ -362,15 +156,8 @@ struct command* parse_command(char* str)
|
||||||
struct command* ret = ccalloc(sizeof(struct command) + strlen(copy) * sizeof(char*), 1);
|
struct command* ret = ccalloc(sizeof(struct command) + strlen(copy) * sizeof(char*), 1);
|
||||||
parser_allocated(ret);
|
parser_allocated(ret);
|
||||||
|
|
||||||
char* p = copy;
|
while ((token = next_non_empty(©)))
|
||||||
|
|
||||||
while (*p)
|
|
||||||
{
|
{
|
||||||
char* token = parse_token(&p);
|
|
||||||
|
|
||||||
if (!token)
|
|
||||||
break;
|
|
||||||
|
|
||||||
ret->argv[i++] = token;
|
ret->argv[i++] = token;
|
||||||
}
|
}
|
||||||
ret->redirect[0] = ret->redirect[1] = -1;
|
ret->redirect[0] = ret->redirect[1] = -1;
|
||||||
|
|
@ -384,86 +171,32 @@ struct command* parse_command(char* str)
|
||||||
*/
|
*/
|
||||||
struct pipeline* parse_pipeline(char *str)
|
struct pipeline* parse_pipeline(char *str)
|
||||||
{
|
{
|
||||||
char* copy = strndup(str, max_length);
|
char* copy = strndup(str, max_lenght);
|
||||||
parser_allocated(copy);
|
parser_allocated(copy);
|
||||||
|
char* cmd_str;
|
||||||
|
int n_cmds = 0;
|
||||||
|
int i = 0;
|
||||||
|
struct pipeline* ret;
|
||||||
|
|
||||||
size_t cap = 4;
|
/*
|
||||||
size_t count = 0;
|
* Count pipe characters that appear in pipeline to know how much space to
|
||||||
struct command** cmds = malloc(sizeof(struct command*) * cap);
|
* allocate for the cmds array.
|
||||||
if (!cmds)
|
*/
|
||||||
|
for (char* cur = str; *cur; cur++)
|
||||||
{
|
{
|
||||||
perror("malloc");
|
if (*cur == '|') ++n_cmds;
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int in_single = 0;
|
++n_cmds; /* There is one more command than there are pipe characters. */
|
||||||
int in_double = 0;
|
|
||||||
int in_backtick = 0;
|
|
||||||
int paren_depth = 0;
|
|
||||||
|
|
||||||
char* start = copy;
|
|
||||||
char* p = copy;
|
|
||||||
|
|
||||||
while (*p)
|
|
||||||
{
|
|
||||||
if (!in_double && !in_backtick && *p == '\'')
|
|
||||||
in_single = !in_single;
|
|
||||||
|
|
||||||
else if (!in_single && !in_backtick && *p == '"')
|
|
||||||
in_double = !in_double;
|
|
||||||
|
|
||||||
else if (!in_single && !in_double && *p == '`')
|
|
||||||
in_backtick = !in_backtick;
|
|
||||||
|
|
||||||
else if (!in_single && !in_double && !in_backtick)
|
|
||||||
{
|
|
||||||
if (*p == '$' && *(p+1) == '(')
|
|
||||||
{
|
|
||||||
paren_depth++;
|
|
||||||
p++; // skip '(' next iteration
|
|
||||||
}
|
|
||||||
else if (*p == '(' && paren_depth > 0)
|
|
||||||
{
|
|
||||||
paren_depth++;
|
|
||||||
}
|
|
||||||
else if (*p == ')' && paren_depth > 0)
|
|
||||||
{
|
|
||||||
paren_depth--;
|
|
||||||
}
|
|
||||||
else if (*p == '|' && paren_depth == 0)
|
|
||||||
{
|
|
||||||
*p = '\0';
|
|
||||||
|
|
||||||
if (count >= cap)
|
|
||||||
{
|
|
||||||
cap *= 2;
|
|
||||||
cmds = realloc(cmds, sizeof(struct command*) * cap);
|
|
||||||
if (!cmds)
|
|
||||||
{
|
|
||||||
perror("realloc");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cmds[count++] = parse_command(start);
|
|
||||||
start = p + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
|
|
||||||
cmds[count++] = parse_command(start);
|
|
||||||
|
|
||||||
struct pipeline* ret =
|
|
||||||
ccalloc(sizeof(struct pipeline) + count * sizeof(struct command*), 1);
|
|
||||||
|
|
||||||
|
ret = ccalloc(sizeof(struct pipeline) + n_cmds * sizeof(struct command*), 1);
|
||||||
parser_allocated(ret);
|
parser_allocated(ret);
|
||||||
parser_allocated(cmds);
|
ret->n_cmds = n_cmds;
|
||||||
ret->n_cmds = count;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < count; i++)
|
while((cmd_str = strsep(&str, "|")))
|
||||||
ret->cmds[i] = cmds[i];
|
{
|
||||||
|
ret->cmds[i++] = parse_command(cmd_str);
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
@ -496,7 +229,6 @@ static struct sigaction s_old;
|
||||||
|
|
||||||
pid_t run_with_redir(struct command* command, int n_pipes, int (*pipes)[2])
|
pid_t run_with_redir(struct command* command, int n_pipes, int (*pipes)[2])
|
||||||
{
|
{
|
||||||
|
|
||||||
pid_t child_pid = fork();
|
pid_t child_pid = fork();
|
||||||
|
|
||||||
if(child_pid < 0)
|
if(child_pid < 0)
|
||||||
|
|
@ -522,118 +254,10 @@ int cd(char* path)
|
||||||
return chdir(path);
|
return chdir(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
int execute_pipeline(struct pipeline* pl, int capture, char** out)
|
|
||||||
{
|
|
||||||
int n_pipes = pl->n_cmds - 1;
|
|
||||||
int (*pipes)[2] = ccalloc(sizeof(int[2]), n_pipes);
|
|
||||||
parser_allocated(pipes);
|
|
||||||
|
|
||||||
for (int i = 1; i < pl->n_cmds; ++i)
|
|
||||||
{
|
|
||||||
pipe(pipes[i-1]);
|
|
||||||
pl->cmds[i]->redirect[STDIN_FILENO] = pipes[i-1][0];
|
|
||||||
pl->cmds[i-1]->redirect[STDOUT_FILENO] = pipes[i-1][1];
|
|
||||||
}
|
|
||||||
|
|
||||||
int capture_pipe[2];
|
|
||||||
|
|
||||||
if (capture)
|
|
||||||
{
|
|
||||||
pipe(capture_pipe);
|
|
||||||
pl->cmds[pl->n_cmds - 1]->redirect[STDOUT_FILENO] = capture_pipe[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
pid_t* pids = ccalloc(sizeof(pid_t), pl->n_cmds);
|
|
||||||
parser_allocated(pids);
|
|
||||||
|
|
||||||
for (int i = 0; i < pl->n_cmds; ++i)
|
|
||||||
{
|
|
||||||
struct command* cmd = pl->cmds[i];
|
|
||||||
char* cmd_name = command_name(cmd);
|
|
||||||
if(!cmd_name)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if(strlen(cmd_name) >= 1 && cmd_name[0] == '#')
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(strcmp(cmd_name, "cd") == 0)
|
|
||||||
{
|
|
||||||
char* path = cmd->argv[1] ? cmd->argv[1] : getenv("HOME");
|
|
||||||
if (cd(path) < 0)
|
|
||||||
{
|
|
||||||
char err_buf[max_length] = {0};
|
|
||||||
sprintf(err_buf, "cd: %s", path);
|
|
||||||
perror(err_buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if(strcmp(cmd_name, "exit") == 0)
|
|
||||||
{
|
|
||||||
int32_t status_code = cmd->argv[1] != NULL ? atoi(cmd->argv[1]) : 0;
|
|
||||||
exit(status_code);
|
|
||||||
}
|
|
||||||
|
|
||||||
pids[i] = run_with_redir(cmd, n_pipes, pipes);
|
|
||||||
}
|
|
||||||
|
|
||||||
close_ALL_the_pipes(n_pipes, pipes);
|
|
||||||
|
|
||||||
if (capture)
|
|
||||||
close(capture_pipe[1]);
|
|
||||||
|
|
||||||
int status;
|
|
||||||
for (int i = 0; i < pl->n_cmds; ++i)
|
|
||||||
waitpid(pids[i], &status, 0);
|
|
||||||
|
|
||||||
if (capture)
|
|
||||||
{
|
|
||||||
char buffer[max_length];
|
|
||||||
size_t total = 0;
|
|
||||||
char* result = NULL;
|
|
||||||
ssize_t n;
|
|
||||||
|
|
||||||
while ((n = read(capture_pipe[0], buffer, sizeof(buffer))) > 0)
|
|
||||||
{
|
|
||||||
result = realloc(result, total + n + 1);
|
|
||||||
memcpy(result + total, buffer, n);
|
|
||||||
total += n;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!result)
|
|
||||||
result = strdup("");
|
|
||||||
|
|
||||||
result[total] = '\0';
|
|
||||||
|
|
||||||
if (total > 0 && result[total-1] == '\n')
|
|
||||||
result[total-1] = '\0';
|
|
||||||
parser_allocated(result);
|
|
||||||
*out = result;
|
|
||||||
close(capture_pipe[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return WEXITSTATUS(status);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, const char* argv[])
|
int main(int argc, const char* argv[])
|
||||||
{
|
{
|
||||||
FILE* stream = stdin;
|
FILE* stream = stdin;
|
||||||
char* prompt = "arsh> ";
|
char* prompt = "arsh> ";
|
||||||
const bool spawn_command = argc >= 2 && strcmp(argv[1], "-c") == 0;
|
|
||||||
if(spawn_command)
|
|
||||||
{
|
|
||||||
if(argc !=3)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "There must be exactly 3 arguments, when starting with a command '-c', but provided %d\n", argc);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
char* input = strdup(argv[2]);
|
|
||||||
struct pipeline* pipeline = parse_pipeline(input);
|
|
||||||
exit(execute_pipeline(pipeline, 0, NULL));
|
|
||||||
}
|
|
||||||
if(argc == 2)
|
if(argc == 2)
|
||||||
{
|
{
|
||||||
FILE* file = fopen(argv[1], "r");
|
FILE* file = fopen(argv[1], "r");
|
||||||
|
|
@ -670,8 +294,61 @@ int main(int argc, const char* argv[])
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// After that line you need cleanup
|
||||||
struct pipeline* pipeline = parse_pipeline(input);
|
struct pipeline* pipeline = parse_pipeline(input);
|
||||||
execute_pipeline(pipeline, 0, NULL);
|
int n_pipes = pipeline->n_cmds - 1;
|
||||||
|
|
||||||
|
/* pipes[i] redirects from pipeline->cmds[i] to pipeline->cmds[i+1]. */
|
||||||
|
int (*pipes)[2] = ccalloc(sizeof(int[2]), n_pipes);
|
||||||
|
parser_allocated(pipes);
|
||||||
|
pid_t* pids = ccalloc(sizeof(pid_t), pipeline->n_cmds);
|
||||||
|
parser_allocated(pids);
|
||||||
|
for (int i = 1; i < pipeline->n_cmds; ++i)
|
||||||
|
{
|
||||||
|
pipe(pipes[i-1]);
|
||||||
|
pipeline->cmds[i]->redirect[STDIN_FILENO] = pipes[i-1][0];
|
||||||
|
pipeline->cmds[i-1]->redirect[STDOUT_FILENO] = pipes[i-1][1];
|
||||||
|
}
|
||||||
|
for (int i = 0; i < pipeline->n_cmds; ++i)
|
||||||
|
{
|
||||||
|
struct command* cmd = pipeline->cmds[i];
|
||||||
|
char* cmd_name = command_name(cmd);
|
||||||
|
if(!cmd_name)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(strlen(cmd_name) >= 1 && cmd_name[0] == '#')
|
||||||
|
{
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(strcmp(cmd_name, "cd") == 0)
|
||||||
|
{
|
||||||
|
char* path = cmd->argv[1] ? cmd->argv[1] : getenv("HOME");
|
||||||
|
if (cd(path) < 0)
|
||||||
|
{
|
||||||
|
char err_buf[max_lenght] = {0};
|
||||||
|
sprintf(err_buf, "cd: %s", path);
|
||||||
|
perror(err_buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
goto cleanup; //skip fork()
|
||||||
|
}
|
||||||
|
if(strcmp(cmd_name, "exit") == 0)
|
||||||
|
{
|
||||||
|
int32_t status_code = cmd->argv[1] != NULL ? atoi(cmd->argv[1]) : 0;
|
||||||
|
exit(status_code);
|
||||||
|
}
|
||||||
|
pids[i] = run_with_redir(cmd, n_pipes, pipes);
|
||||||
|
}
|
||||||
|
close_ALL_the_pipes(n_pipes, pipes);
|
||||||
|
|
||||||
|
for(size_t i = 0; i < pipeline->n_cmds; i++)
|
||||||
|
{
|
||||||
|
waitpid(pids[i], &stat_loc, WUNTRACED);
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
|
||||||
parser_free();
|
parser_free();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue