1// SPDX-License-Identifier: GPL-3.0-or-later
2
3#pragma once
4
5#include <filesystem>
6#include <map>
7#include <memory>
8#include <ostream>
9#include <string>
10#include <vector>
11
12struct BaseRedirection
13{
14 enum IOMode
15 {
16 ReadOnly = 1,
17 WriteOnly = 2,
18 ReadWrite = 3
19 };
20
21 IOMode mode = ReadOnly;
22 bool append = false;
23
24 virtual ~BaseRedirection() = default;
25 virtual bool do_redirect(int fd) = 0;
26};
27
28struct FDRedirection : public BaseRedirection
29{
30 FDRedirection(int target_fd, IOMode mode) : target_fd(target_fd)
31 {
32 this->mode = mode;
33 }
34
35 bool do_redirect(int fd) override;
36 int target_fd = -1;
37};
38
39struct FileRedirection : public BaseRedirection
40{
41 FileRedirection(const std::filesystem::path &file, IOMode mode, bool append) : file(file)
42 {
43 this->mode = mode;
44 this->append = append;
45 }
46
47 bool do_redirect(int fd) override;
48 std::filesystem::path file;
49};
50
51enum token_type
52{
53 TEXT, // normal text
54 REDIRECT_IN, // <
55 REDIRECT_OUT, // >
56 REDIRECT_APPEND, // >>
57 PIPE, // |
58 BACKGROUND, // &
59 END // end of command
60};
61
62struct token
63{
64 token_type type;
65 std::string tstring;
66 token(token_type type) : type(type), tstring() {};
67 token(const std::string &tstring) : type(TEXT), tstring(tstring) {};
68
69 friend std::ostream &operator<<(std::ostream &os, const token &t)
70 {
71 switch (t.type)
72 {
73 case TEXT: return os << "TEXT(" << t.tstring << ")";
74 case REDIRECT_IN: os << "REDIRECT_IN"; break;
75 case REDIRECT_OUT: os << "REDIRECT_OUT"; break;
76 case REDIRECT_APPEND: os << "REDIRECT_APPEND"; break;
77 case PIPE: os << "PIPE"; break;
78 case BACKGROUND: os << "BACKGROUND"; break;
79 case END: break;
80 }
81 return os;
82 }
83};
84
85struct ProgramSpec
86{
87 std::vector<std::string> argv;
88 std::map<int, std::unique_ptr<BaseRedirection>> redirections;
89 bool background = false; // only valid for the last program in the pipeline
90
91 friend std::ostream &operator<<(std::ostream &os, const ProgramSpec &program)
92 {
93 for (const auto &arg : program.argv)
94 os << arg << ' ';
95 os << std::endl;
96
97 return os;
98 }
99};
100
101std::unique_ptr<ProgramSpec> parse_commandline(const std::string &command);
102