forked from veluca93/tmbox
-
Notifications
You must be signed in to change notification settings - Fork 0
/
options.h
132 lines (104 loc) · 4.55 KB
/
options.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#pragma once
#include <optional>
#include <string.h>
#include <string>
#include <tuple>
#include <vector>
#define DEFINE_FLAG(type, name, lng, srt, desc) \
struct name : public detail::Flag<type> { \
static constexpr const bool is_positional = false; \
static constexpr const char *const long_name = lng; \
static constexpr const char short_name = srt; \
static constexpr const char *const description = desc; \
};
#define DEFINE_POSITIONAL(type, cls, nm, req, desc) \
struct cls : public detail::Flag<type> { \
static constexpr const bool is_positional = true; \
static constexpr const bool required = req; \
static constexpr const char *const name = nm; \
static constexpr const char *const description = desc; \
};
namespace options {
namespace detail {
template <typename T> struct Flag {
using type = T;
T value{};
bool parsed = false;
void ParseValue(const char *input);
static constexpr const bool has_value = true;
};
template <> struct Flag<bool> {
using type = bool;
bool value = false;
bool parsed = false;
static constexpr const bool has_value = false;
};
}; // namespace detail
DEFINE_FLAG(std::string, WorkingDirectory, "directory", 'd',
"Working directory for the execution. Defaults to the current "
"directory.");
DEFINE_FLAG(std::string, Stdin, "stdin", 'i',
"Absolute/relative path to stdin file.");
DEFINE_FLAG(std::string, Stdout, "stdout", 'o',
"Absolute/relative path to stdout file.");
DEFINE_FLAG(std::string, Stderr, "stderr", 'e',
"Absolute/relative path to stderr file.");
DEFINE_FLAG(double, TimeLimit, "time", 't', "CPU time limit, in seconds.");
DEFINE_FLAG(double, WallLimit, "wall", 'w', "Wall time limit, in seconds.");
DEFINE_FLAG(uint64_t, MemoryLimit, "memory", 'm', "Memory limit, in KiB.");
DEFINE_FLAG(uint64_t, FsizeLimit, "fsize", 'f', "File size limit, in KiB.");
struct EnvironmentVariable {
std::string name;
std::optional<std::string> value;
};
DEFINE_FLAG(
std::vector<EnvironmentVariable>, Environment, "env", 'E',
"Environment variables, in the form NAME=VALUE. Variables with no value "
"inherit the value from the global environment.");
DEFINE_FLAG(std::vector<std::string>, ReadableDir, "readable-dir", 'r',
"Allow the sandbox to read files from this directory.");
DEFINE_FLAG(bool, Multiprocess, "multiprocess", 'p',
"Allow more than one process. Warning: may not properly enforce "
"limits/report resource usage!");
DEFINE_FLAG(bool, AllowChmod, "allow-chmod", 'c', "Allow using chmod.");
DEFINE_FLAG(bool, MountTmpfs, "mount-tmpfs", 'T', "Mount inside the sandbox /tmp and /dev/null");
DEFINE_FLAG(bool, Json, "json", 'j', "Print JSON output");
DEFINE_FLAG(std::string, Stats, "stats", 's',
"File to write runtime stats to (defaults to stdout)");
using Flags = std::tuple<WorkingDirectory, Stdin, Stdout, Stderr, TimeLimit,
WallLimit, MemoryLimit, FsizeLimit, Environment,
ReadableDir, Multiprocess, AllowChmod, MountTmpfs, Json, Stats>;
// Positional arguments.
DEFINE_POSITIONAL(
std::string, Executable, "executable", true,
"Executable to run. Either absolute path, or relative to the specified "
"working directory.");
DEFINE_POSITIONAL(std::vector<std::string>, Args, "args", false,
"Other arguments to the executable.");
using Positional = std::tuple<Executable, Args>;
struct Options {
Flags flags;
Positional positional;
static constexpr const char *const description =
"Runs a program under limited privileges, collecting running time and "
"memory usage statistics.";
template <typename Flag>
const typename Flag::type &Get(Flag flag = Flag()) const {
if constexpr (Flag::is_positional) {
return std::get<Flag>(positional).value;
} else {
return std::get<Flag>(flags).value;
}
}
template <typename Flag> const bool &Has(Flag flag = Flag()) const {
if constexpr (Flag::is_positional) {
return std::get<Flag>(positional).parsed;
} else {
return std::get<Flag>(flags).parsed;
}
}
};
Options ParseCommandLine(int argc, char **argv);
} // namespace options
#undef DEFINE_FLAG
#undef DEFINE_POSITIONAL