diff options
Diffstat (limited to 'exec.c')
| -rw-r--r-- | exec.c | 188 |
1 files changed, 50 insertions, 138 deletions
@@ -9,108 +9,10 @@ #include "utils.h" #include "exec.h" #include "preproc.h" +#include "expand.h" -char* get_var(char* varname, ShellState* shstate) { - MaybeStr maybe_varval = get_map_value(&shstate->shell_vars, varname); - if (maybe_varval.some == true) return maybe_varval.value; - return getenv(varname); -} - -typedef struct { - QuotationMode qmode; - char* content; -} ExpandedChunk; - - -ExpandedChunk expand_chunk(Chunk chunk, ShellState* shstate) { - char* content; - if (chunk.qmode == SINGLE_Q || chunk.kind == LITERAL) { - if (chunk.qmode == SINGLE_Q && chunk.kind != LITERAL) exit(69); - content = chunk.as.literal_str; - } else if (chunk.kind == VAR_EXP) { - content = get_var(chunk.as.varname, shstate); - } else if (chunk.kind == REGION_EXP) { - exit(7); // Not supported yet; arithm - } - return (ExpandedChunk){.qmode = chunk.qmode, .content = content}; -} - - -typedef struct { - StrVec complete_strs; - String active_str; -} WordSplittingGerm; - -void add_expchunk(char* next_str, WordSplittingGerm* curr_res) { - for (int pos = 0; pos < strlen(next_str); pos++) { - if (next_str[pos] == ' ') { - push_to_StrVec(&curr_res->complete_strs, inner(&curr_res->active_str)); - curr_res->active_str = make_String(256); - } else { - push_to_String(&curr_res->active_str, next_str[pos]); - } - } -} - -StrVec expand_word(Word word, ShellState* state) { - WordSplittingGerm curr_res = {.complete_strs = make_StrVec(256), .active_str = make_String(25)}; - for (int i = 0; i < word.count; i++) { - Chunk curr_cunk = **get_from_Word(&word, i); - ExpandedChunk curr_exp = expand_chunk(curr_cunk, state); - switch (curr_exp.qmode) { - case UN_Q: - add_expchunk(curr_exp.content, &curr_res); - break; - case SINGLE_Q: - append_str_to_String(&curr_res.active_str, curr_exp.content); - break; - case DOUBLE_Q: - append_str_to_String(&curr_res.active_str, curr_exp.content); - } - } - - if (curr_res.active_str.count > 0) { - push_to_StrVec(&curr_res.complete_strs, inner(&curr_res.active_str)); - } - - return curr_res.complete_strs; -} - - -void merge_strvecs(StrVec* target, StrVec* source) { - for (int i = 0; i < source->count; i++) { - push_to_StrVec(target, *get_from_StrVec(source, i)); - } -} - - -char** make_cmd_args(Command command, ShellState* shstate) { - StrVec arg_str_vec = make_StrVec(256); - for (int i = 0; i < command.args.count; i++) { - Token arg_i = *get_from_TokenVec(&command.args, i); - StrVec expanded_i; - switch (arg_i.kind) { - case TOK_WORD: - expanded_i = expand_word(arg_i.as.word, shstate); - merge_strvecs(&arg_str_vec, &expanded_i); - break; - default: - exit(67); - } - } - int argcount = arg_str_vec.count; - char** arg_str_arr = malloc(sizeof(char*) * (argcount + 1)); - for (int j = 0; j < argcount; j++) { - arg_str_arr[j] = *get_from_StrVec(&arg_str_vec, j); - } - arg_str_arr[argcount] = NULL; - return arg_str_arr; -} - - - -void execute_command(ExecutableCommand cmd, int* pgid) { +void execute_command(Command cmd, int* pgid) { pid_t pid = fork(); if (pid == 0) { @@ -150,58 +52,55 @@ void execute_command(ExecutableCommand cmd, int* pgid) { } } +Command make_command(SlotVec cmd_slots) { + Command cmd = { + .child_close_fds = make_IntVec(64), + .parent_close_fds = make_IntVec(64), + .redirs = make_FdRedirectVec(32) + }; + StrVec arg_strs = make_StrVec(256); + for (int i = 0; i < cmd_slots.count; i++) { + Slot slot = *get_from_SlotVec(&cmd_slots, i); + switch (slot.kind) { + case SLOT_STR: + push_to_StrVec(&arg_strs, slot.as.str); + default: + exit(67); + // TODO: other slot kinds + } + } + cmd.args = malloc(sizeof(char*) * arg_strs.count); + for (int j = 0; j < arg_strs.count; j++) { + cmd.args[j] = *get_from_StrVec(&arg_strs, j); + } + return cmd; +} - -void run_pipeline(Pipeline pl, ShellState* shstate) { +void run_cmds(CommandVec cmds) { signal(SIGTTIN, SIG_IGN); signal(SIGTTOU, SIG_IGN); - int last_pipe_fd; + int trunk_fd = STDIN_FILENO; int pgid = -1; - for (int i = 0; i < pl.count; i++) { - PipelineElement elem = *get_from_Pipeline(&pl, i); - ExecutableCommand cmd = { - .child_close_fds = make_IntVec(64), - .parent_close_fds = make_IntVec(64), - .redirs = make_FdRedirectVec(32) - }; - cmd.args = make_cmd_args(elem.cmd, shstate); + for (int i = 0; i < cmds.count; i++) { + Command cmd = *get_from_CommandVec(&cmds, i); + cmd.stdin_fd = trunk_fd; - if (i == 0) { - cmd.stdin_fd = STDIN_FILENO; - } else { - cmd.stdin_fd = last_pipe_fd; - push_to_IntVec(&cmd.child_close_fds, last_pipe_fd); - push_to_IntVec(&cmd.parent_close_fds, last_pipe_fd); + if (i > 0) { + push_to_IntVec(&cmd.child_close_fds, trunk_fd); + push_to_IntVec(&cmd.parent_close_fds, trunk_fd); } - if (elem.conn == CONN_PIPE) { + cmd.stdout_fd = STDOUT_FILENO; + if (cmd.term = CONN_PIPE) { int pipe_fds[2]; pipe(pipe_fds); cmd.stdout_fd = pipe_fds[1]; push_to_IntVec(&cmd.child_close_fds, pipe_fds[1]); push_to_IntVec(&cmd.parent_close_fds, pipe_fds[1]); - last_pipe_fd = pipe_fds[0]; - } else { - cmd.stdout_fd = STDOUT_FILENO; - } - - for (int j = 0; j < elem.cmd.redirects.count; j++) { - Redirect rd = *get_from_RedirectVec(&elem.cmd.redirects, j); - switch (rd.kind) { - case STDIN_REDIR: - /* - int in_fd = open(rd.as.std_redir_filename, O_RDONLY, 0644); - push_to_FdRedirectVec(&cmd.redirs, (FdRedirect){.old_fd = STDIN_REDIR, .new_fd = in_fd}); - push_to_IntVec(&cmd.child_close_fds, in_fd); - push_to_IntVec(&cmd.parent_close_fds, in_fd); - */ - break; - default: - exit(69); - } + trunk_fd = pipe_fds[0]; } execute_command(cmd, &pgid); @@ -210,12 +109,23 @@ void run_pipeline(Pipeline pl, ShellState* shstate) { close(*get_from_IntVec(&cmd.parent_close_fds, j)); } } + tcsetpgrp(STDIN_FILENO, pgid); while (waitpid(-pgid, NULL, 0) > 0); tcsetpgrp(STDIN_FILENO, getpgrp()); } +CommandVec make_cmd_vec_pl(ExpandedPipeline pl) { + CommandVec cmds = make_CommandVec(256); + for (int i = 0; i < pl.count; i++) { + ExpandedPipelineElement elem = *get_from_ExpandedPipeline(&pl, i); + Command cmd = make_command(elem.cmd_slots); + push_to_CommandVec(&cmds, cmd); + } +} + + void process_input_line(char* line, ShellState* shstate) { PreprocArena arena = { .tokens = make_TokenVec(256), @@ -228,7 +138,9 @@ void process_input_line(char* line, ShellState* shstate) { line_toks[i] = **get_from_TokenPtrVec(&line_tok_ptrs, i); } Pipeline pl = parse_tokstream(line_toks); - run_pipeline(pl, shstate); + ExpandedPipeline exp_pl = expand_pipeline(&pl, shstate); + CommandVec cmds = make_cmd_vec_pl(exp_pl); + run_cmds(cmds); free(line_toks); } |
