myshell 2.0.0
Loading...
Searching...
No Matches
msh_redirect.h
1//
2// Created by andrew on 11/2/23.
3//
4
5#ifndef MYSHELL_MSH_REDIRECT_H
6#define MYSHELL_MSH_REDIRECT_H
7
8#include "internal/msh_error.h"
9#include "msh_token.h"
10
11#include <string>
12#include <vector>
13#include <utility>
14#include <fcntl.h>
15#include <unistd.h>
16#include <cstring>
17
18
19struct redirect;
20using redirects_t = std::vector<redirect>;
21
29struct redirectee {
30 int fd = -1;
31 std::string path;
32
46 [[nodiscard]]
47 int open_redirect(std::vector<int> *fd_to_close, int flags, int mode) const {
48 int res = -1;
49 if (this->fd != -1) {
50 res = this->fd;
51 } else if (!path.empty()) {
52 res = open(path.c_str(), flags, mode);
53 if (res == -1) {
54 msh_error("cannot open " + path + ": " + strerror(errno));
55 return -1;
56 }
57 if (fd_to_close != nullptr) {
58 fd_to_close->push_back(res);
59 }
60 }
61 return res;
62 }
63};
64
72struct redirect {
73 struct redirectee in;
74 struct redirectee out;
75 bool both_err_out = false;
76
77 enum {
78 NONE,
79 OUT,
80 OUT_APPEND,
81 IN,
82 } type = NONE;
83
84 explicit redirect(const Token& redirect_token) {
85 switch (redirect_token.type) {
86 case TokenType::IN:
87 case TokenType::IN_AMP:
88 type = IN;
89 in.fd = STDIN_FILENO;
90 break;
91 case TokenType::AMP_OUT:
92 both_err_out = true;
93 [[fallthrough]];
94 case TokenType::OUT_AMP:
95 case TokenType::OUT:
96 type = OUT;
97 in.fd = STDOUT_FILENO;
98 break;
99 case TokenType::AMP_APPEND:
100 both_err_out = true;
101 [[fallthrough]];
102 case TokenType::OUT_APPEND:
103 type = OUT_APPEND;
104 in.fd = STDOUT_FILENO;
105 break;
106 default:
107 break;
108 }
109 }
110
122 [[nodiscard]] int do_redirect(std::vector<int> *fd_to_close) const {
123 if (type == NONE) {
124 return 0;
125 }
126 int flags, mode = 0;
127
128 switch (type) {
129 case OUT:
130 flags = O_WRONLY | O_CREAT | O_TRUNC;
131 mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
132 break;
133 case OUT_APPEND:
134 flags = O_WRONLY | O_CREAT | O_APPEND;
135 mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
136 break;
137 case IN:
138 flags = O_RDONLY;
139 break;
140 default:
141 return 0;
142 }
143
144 int in_fd, out_fd;
145 in_fd = in.open_redirect(fd_to_close, flags, mode);
146 out_fd = out.open_redirect(fd_to_close, flags, mode);
147
148 if (in_fd != -1 && out_fd != -1) {
149 if (dup2(out_fd, in_fd) == -1) {
150 msh_error("cannot redirect: " + std::string(strerror(errno)));
151 return 1;
152 }
153 }
154
155 if (both_err_out) {
156 if (dup2(STDOUT_FILENO, STDERR_FILENO) == -1) {
157 msh_error("cannot redirect: " + std::string(strerror(errno)));
158 return 1;
159 }
160 }
161 return 0;
162 }
163};
164
165
166#endif //MYSHELL_MSH_REDIRECT_H
void msh_error(const std::string &msg)
Print an error message to stderr with a myshell: prefix.
Definition msh_error.cpp:37
Token structure and related types.
Structure representing a token.
Definition msh_token.h:74
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
Structure representing a single redirectee.
Definition msh_redirect.h:29
int open_redirect(std::vector< int > *fd_to_close, int flags, int mode) const
Opens the redirection target.
Definition msh_redirect.h:47