summaryrefslogtreecommitdiff
path: root/src/exec.c
diff options
context:
space:
mode:
authorÁkos Kőrösi <korakos99@gmail.com>2026-05-19 21:13:19 +0200
committerÁkos Kőrösi <korakos99@gmail.com>2026-05-19 21:13:19 +0200
commit2bdbf387261285d07e4b62d1e23c9e43efb14604 (patch)
tree92b81d300f3c17d072f2a30362dafd815e57a758 /src/exec.c
parent6a391a1180766ac5717c40efa70d46cacca83f91 (diff)
restructure dir, create makefile
Diffstat (limited to 'src/exec.c')
-rw-r--r--src/exec.c189
1 files changed, 189 insertions, 0 deletions
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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/wait.h>
+
+#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);
+}
+