1 #include "config.h"  // IWYU pragma: keep
2 
3 #include "redirection.h"
4 
5 #include <fcntl.h>
6 
7 #include "io.h"
8 #include "wutil.h"
9 
10 dup2_list_t::~dup2_list_t() = default;
11 
get_target_as_fd() const12 maybe_t<int> redirection_spec_t::get_target_as_fd() const {
13     errno = 0;
14     int result = fish_wcstoi(target.c_str());
15     if (errno || result < 0) return none();
16     return result;
17 }
18 
oflags() const19 int redirection_spec_t::oflags() const {
20     switch (mode) {
21         case redirection_mode_t::append:
22             return O_CREAT | O_APPEND | O_WRONLY;
23         case redirection_mode_t::overwrite:
24             return O_CREAT | O_WRONLY | O_TRUNC;
25         case redirection_mode_t::noclob:
26             return O_CREAT | O_EXCL | O_WRONLY;
27         case redirection_mode_t::input:
28             return O_RDONLY;
29         case redirection_mode_t::fd:
30         default:
31             DIE("Not a file redirection");
32     }
33 }
34 
resolve_chain(const io_chain_t & io_chain)35 dup2_list_t dup2_list_t::resolve_chain(const io_chain_t &io_chain) {
36     ASSERT_IS_NOT_FORKED_CHILD();
37     dup2_list_t result;
38     for (const auto &io : io_chain) {
39         if (io->source_fd < 0) {
40             result.add_close(io->fd);
41         } else {
42             result.add_dup2(io->source_fd, io->fd);
43         }
44     }
45     return result;
46 }
47 
fd_for_target_fd(int target) const48 int dup2_list_t::fd_for_target_fd(int target) const {
49     // Paranoia.
50     if (target < 0) {
51         return target;
52     }
53     // Note we can simply walk our action list backwards, looking for src -> target dups.
54     int cursor = target;
55     for (auto iter = actions_.rbegin(); iter != actions_.rend(); ++iter) {
56         if (iter->target == cursor) {
57             // cursor is replaced by iter->src
58             cursor = iter->src;
59         } else if (iter->src == cursor && iter->target < 0) {
60             // cursor is closed.
61             cursor = -1;
62             break;
63         }
64     }
65     return cursor;
66 }
67