#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.old_fd, fd_rd.new_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(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_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.cmd_slots); push_to_CommandVec(&cmds, cmd); } } 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); }