From 2bdbf387261285d07e4b62d1e23c9e43efb14604 Mon Sep 17 00:00:00 2001 From: Ákos Kőrösi Date: Tue, 19 May 2026 21:13:19 +0200 Subject: restructure dir, create makefile --- src/exec.c | 189 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 189 insertions(+) create mode 100644 src/exec.c (limited to 'src/exec.c') diff --git a/src/exec.c b/src/exec.c new file mode 100644 index 0000000..fccda7a --- /dev/null +++ b/src/exec.c @@ -0,0 +1,189 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "utils.h" +#include "exec.h" +#include "preproc.h" +#include "expand.h" + + +void execute_command(Command cmd, int* pgid) { + + pid_t pid = fork(); + + if (pid == 0) { + if (*pgid == -1) { + setpgid(0, 0); + } else { + setpgid(0, *pgid); + } + + dup2(cmd.stdin_fd, STDIN_FILENO); + dup2(cmd.stdout_fd, STDOUT_FILENO); + + for (int j = 0; j < cmd.redirs.count; j++) { + FdRedirect fd_rd = *get_from_FdRedirectVec(&cmd.redirs, j); + dup2(fd_rd.new_fd, fd_rd.old_fd); + } + + for (int i = 0; i < cmd.child_close_fds.count; i++) { + close(*get_from_IntVec(&cmd.child_close_fds, i)); + } + + signal(SIGINT, SIG_DFL); + signal(SIGQUIT, SIG_DFL); + signal(SIGTSTP, SIG_DFL); + signal(SIGTTIN, SIG_DFL); + signal(SIGTTOU, SIG_DFL); + + execvp(cmd.args[0], cmd.args); + exit(67); + } + + if (*pgid == -1) { + setpgid(pid, pid); + *pgid = pid; + } else { + setpgid(pid, *pgid); + } +} + +Command make_command(ExpandedPipelineElement elem) { + Command cmd = { + .child_close_fds = make_IntVec(64), + .parent_close_fds = make_IntVec(64), + .redirs = make_FdRedirectVec(32), + .term = elem.conn, + }; + StrVec arg_strs = make_StrVec(256); + for (int i = 0; i < elem.cmd_slots.count; i++) { + Slot curr_slot = *get_from_SlotVec(&elem.cmd_slots, i); + Slot next_slot; + int fd; + FdRedirect redir; + switch (curr_slot.kind) { + case SLOT_STR: + push_to_StrVec(&arg_strs, curr_slot.as.str); + break; + case SLOT_SPEC: + switch (curr_slot.as.spec) { + case READ_REDIR: + i++; + next_slot = *get_from_SlotVec(&elem.cmd_slots, i); + if (next_slot.kind != SLOT_STR) exit(6); + fd = open(next_slot.as.str, O_RDONLY, 0644); + redir = (FdRedirect){.old_fd = STDIN_FILENO, .new_fd = fd}; + push_to_FdRedirectVec(&cmd.redirs, redir); + push_to_IntVec(&cmd.parent_close_fds, fd); + push_to_IntVec(&cmd.child_close_fds, fd); + break; + case WRITE_REDIR_TRUNC: + i++; + next_slot = *get_from_SlotVec(&elem.cmd_slots, i); + if (next_slot.kind != SLOT_STR) exit(6); + fd = open(next_slot.as.str, O_WRONLY | O_CREAT | O_TRUNC , 0644); + redir = (FdRedirect){.old_fd = STDOUT_FILENO, .new_fd = fd}; + push_to_FdRedirectVec(&cmd.redirs, redir); + push_to_IntVec(&cmd.parent_close_fds, fd); + push_to_IntVec(&cmd.child_close_fds, fd); + break; + case WRITE_REDIR_APPEND: + i++; + next_slot = *get_from_SlotVec(&elem.cmd_slots, i); + if (next_slot.kind != SLOT_STR) exit(6); + fd = open(next_slot.as.str, O_WRONLY | O_CREAT | O_APPEND, 0644); + redir = (FdRedirect){.old_fd = STDOUT_FILENO, .new_fd = fd}; + push_to_FdRedirectVec(&cmd.redirs, redir); + push_to_IntVec(&cmd.parent_close_fds, fd); + push_to_IntVec(&cmd.child_close_fds, fd); + break; + default: + exit(7); + } + break; + 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_cmds(CommandVec cmds) { + signal(SIGTTIN, SIG_IGN); + signal(SIGTTOU, SIG_IGN); + + int trunk_fd = STDIN_FILENO; + int pgid = -1; + + for (int i = 0; i < cmds.count; i++) { + Command cmd = *get_from_CommandVec(&cmds, i); + cmd.stdin_fd = trunk_fd; + + if (i > 0) { + push_to_IntVec(&cmd.child_close_fds, trunk_fd); + push_to_IntVec(&cmd.parent_close_fds, trunk_fd); + } + + 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]); + trunk_fd = pipe_fds[0]; + } + + execute_command(cmd, &pgid); + + for (int j = 0; j < cmd.parent_close_fds.count; j++) { + 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); + push_to_CommandVec(&cmds, cmd); + } + return cmds; +} + + +void process_input_line(char* line, ShellState* shstate) { + PreprocArena arena = { + .tokens = make_TokenVec(256), + .chunks = make_ChunkVec(256), + .regions = make_RegionVec(256), + }; + TokenPtrVec line_tok_ptrs = lex(line, &arena); + Token* line_toks = malloc(sizeof(Token) * line_tok_ptrs.count); + for (int i = 0; i < line_tok_ptrs.count; i++) { + line_toks[i] = **get_from_TokenPtrVec(&line_tok_ptrs, i); + } + Pipeline pl = parse_tokstream(line_toks); + ExpandedPipeline exp_pl = expand_pipeline(&pl, shstate); + CommandVec cmds = make_cmd_vec_pl(exp_pl); + run_cmds(cmds); + free(line_toks); +} + -- cgit v1.2.3