8#ifndef TEMPLATE_MSH_COMMAND_H
9#define TEMPLATE_MSH_COMMAND_H
11#include "internal/msh_error.h"
12#include "internal/msh_builtin.h"
13#include "internal/msh_exec.h"
14#include "internal/msh_jobs.h"
15#include "internal/msh_utils.h"
16#include "internal/msh_redirects.h"
18#include "msh_redirect.h"
20#include "msh_command_fwd.h"
21#include "msh_exception.h"
49 std::variant<simple_command_ptr, connection_command_ptr> cmd;
61 int execute(
int in = STDIN_FILENO,
int out = STDOUT_FILENO) {
62 std::visit([
this, &in, &out](
auto &&arg) {
70 void set_flags(
int flag) {
88 using args_t = std::vector<std::string>;
89 using argv_c_t = std::vector<char *>;
90 using redirects_t = std::vector<redirect>;
95 std::array<int, 3> saved_fds{};
96 redirects_t redirects;
99 explicit simple_command(tokens_t tokens) : tokens(std::move(tokens)) {}
109 for (
auto const &token: tokens) {
110 if (token.get_flag(
WORD_LIKE) && !token.value.empty()) {
111 argv.push_back(token.value);
114 for (
auto &arg: argv) {
115 argv_c.push_back(arg.data());
117 argv_c.push_back(
nullptr);
118 return (argc =
static_cast<int>(argv.size())) != 0;
134 if (redirects.empty()) {
138 saved_fds[0] = dup(STDIN_FILENO);
139 saved_fds[1] = dup(STDOUT_FILENO);
140 saved_fds[2] = dup(STDERR_FILENO);
141 for (
auto const &
redirect: redirects) {
160 if (redirects.empty()) {
164 dup2(saved_fds[0], STDIN_FILENO);
165 dup2(saved_fds[1], STDOUT_FILENO);
166 dup2(saved_fds[2], STDERR_FILENO);
167 std::ranges::for_each(saved_fds, close);
168 std::ranges::for_each(fd_to_close, close);
181 int execute(
int in = STDIN_FILENO,
int out = STDOUT_FILENO,
int flags = 0) {
194 is_builtin(argv[0]) ? flags |= BUILTIN : flags |= 0;
230 int execute(
int in = STDIN_FILENO,
int out = STDOUT_FILENO,
int flags = 0) {
231 switch (connector.type) {
232 using enum TokenType;
233 case TokenType::PIPE_AMP:
234 flags |= PIPE_STDERR;
246 return UNKNOWN_ERROR;
266 lhs.set_flags(flags & ASYNC);
267 rhs.set_flags(flags & ASYNC);
269 auto res = flags & FORCE_PIPE ? lhs.
execute(in, out) : lhs.
execute();
270 if ((res == 0 && op == TokenType::AND) || (res != 0 && op == TokenType::OR)) {
290 lhs.set_flags(ASYNC);
291 rhs.set_flags(flags & ASYNC);
311 rhs.set_flags(flags & ASYNC);
334 if (pipe(pipefd) == -1) {
336 return UNKNOWN_ERROR;
339 lhs.set_flags(flags | FORK_NO_WAIT);
340 rhs.set_flags(flags);
347 if (!(flags & FORK_NO_WAIT) && !(flags & ASYNC)) {
Internal exception class.
Definition msh_exception.h:18
constexpr int WORD_LIKE
This token is a potential argument/command that will be forwarded to argv.
Definition msh_token.h:57
bool is_builtin(const std::string &cmd)
Check if a command is a built-in command.
Definition msh_builtin.cpp:47
void msh_error(const std::string &msg)
Print an error message to stderr with a myshell: prefix.
Definition msh_error.cpp:37
int msh_exec_internal(command &cmd, int in, int out, int flags)
Internal command execution function.
Definition msh_exec.cpp:220
int msh_exec_simple(simple_command &cmd, int pipe_in=STDIN_FILENO, int pipe_out=STDOUT_FILENO, int flags=0)
Executes a simple command.
Definition msh_exec.cpp:146
int reap_children()
Wait for all background processes to finish.
Definition msh_jobs.cpp:114
redirects_t parse_redirects(tokens_t &tokens)
Parse redirects from command's tokens.
Definition msh_redirects.cpp:57
Token structure and related types.
void process_tokens(tokens_t &tokens)
Process a vector of tokens.
Definition msh_utils.cpp:519
Structure representing a token.
Definition msh_token.h:74
Top-level command structure.
Definition msh_command.h:48
int execute(int in=STDIN_FILENO, int out=STDOUT_FILENO)
Execute the command.
Definition msh_command.h:61
Connection command structure.
Definition msh_command.h:214
int execute_pipeline(int in, int out, int flags)
Executes pipeline connections, i.e. | and |&.
Definition msh_command.h:332
int execute_sequence(int in, int out, int flags)
Executes sequential connections, i.e. ;.
Definition msh_command.h:310
int execute(int in=STDIN_FILENO, int out=STDOUT_FILENO, int flags=0)
Execute the command.
Definition msh_command.h:230
int execute_conditional(int in, int out, int flags, TokenType op)
Executes conditional connections, i.e. && and ||.
Definition msh_command.h:265
int execute_background(int in, int out, int flags)
Executes background connections, i.e. &.
Definition msh_command.h:289
Structure representing a single redirection.
Definition msh_redirect.h:72
int do_redirect(std::vector< int > *fd_to_close) const
Opens the redirectees with respect to the redirection type and duplicates the appropriate file descri...
Definition msh_redirect.h:122
Simple command structure.
Definition msh_command.h:87
int do_redirects(std::vector< int > *fd_to_close)
Perform redirections attached to the command.
Definition msh_command.h:133
void undo_redirects(std::vector< int > const &fd_to_close)
Undo redirections attached to the command.
Definition msh_command.h:159
int execute(int in=STDIN_FILENO, int out=STDOUT_FILENO, int flags=0)
Execute the command.
Definition msh_command.h:181
bool construct()
Construct the command.
Definition msh_command.h:108