8#include <fmt/ostream.h>
9#include <libassert/assert.hpp>
10#include <range/v3/algorithm/transform.hpp>
20#include <system_error>
23#include <bits/types/siginfo_t.h>
31#include <sys/ptrace.h>
40 return {err, std::generic_category()};
46 ssize_t res =
::write(fd, data.data(), data.size());
61 std::string buffer(count,
'\0');
63 ssize_t res =
::read(fd, buffer.data(), count);
72 DEBUG_ASSERT(res >= 0,
"read result is negative and != -1");
73 buffer.resize(
static_cast<std::size_t
>(res));
96 int res =
::kill(pid, sig);
112 const std::vector<std::string>& envp) {
115 std::vector<char*> cstr_arg_list(args.size() + 2,
nullptr);
116 std::vector<char*> cstr_envp_list(envp.size() + 1,
nullptr);
118 auto to_cstr = [](
const std::string& str) {
return const_cast<char*
>(str.c_str()); };
120 cstr_arg_list.front() =
const_cast<char*
>(exec.c_str());
121 ranges::transform(args, cstr_arg_list.begin() + 1, to_cstr);
122 ranges::transform(envp, cstr_envp_list.begin(), to_cstr);
126 int res =
::execve(exec.data(), cstr_arg_list.data(), cstr_envp_list.data());
133 LOG_DEBUG(
"execve failed (INVALID RETURN CODE = {}): '{}'", res, err);
168 int res =
::open(pathname.c_str(), flags, mode);
182 off_t res =
::lseek(fd, offset, whence);
196 int res =
::dup2(oldfd, newfd);
204 LOG_DEBUG(
"dup2 failed (INVALID RETURN CODE = {}): '{}'", res, err);
218 int res =
::ioctl(fd, request, argp);
238 res =
::fcntl(fd, cmd, arg.value());
259 int res =
::waitid(idtype,
id, &info, options);
278 auto err = std::error_code(errno, std::system_category());
302 int res =
::pipe2(&pipe.read_fd, flags);
319template <
typename AddrT =
void*,
typename DataT =
void*>
321 requires(
sizeof(AddrT) <=
sizeof(
void*) &&
sizeof(DataT) <=
sizeof(
void*))
322inline
Expected<
long>
ptrace(
int request, pid_t pid = 0, AddrT addr = NULL, DataT data = NULL) {
331 long res =
::ptrace(
static_cast<enum __ptrace_request
>(request), pid,
reinterpret_cast<void*
>(addr),
332 reinterpret_cast<void*
>(data));
351 struct ::stat data_result{};
353 int res =
::stat(pathname.c_str(), &data_result);
385 : signal_num_{signal_num} {};
388 operator int()
const {
return signal_num_; }
390 std::string
to_string()
const {
return sigdescr_np(signal_num_); }
404 if (prev_handler == SIG_ERR) {
std::variant wrapper for a partial implementation of C++23's expected type
Definition expected.hpp:34
Value type to behave as a linux signal.
Definition linux.hpp:379
friend std::string format_as(const Signal &from)
Definition linux.hpp:392
std::string to_string() const
Definition linux.hpp:390
Signal(int signal_num)
Definition linux.hpp:384
#define LOG_DEBUG(...)
Definition logging.hpp:44
Expected< Fork > fork()
see dup(2) and ForkExpected returns result from enum; logs failure at debug level
Definition linux.hpp:148
Expected< Pipe > pipe2(int flags=0)
see pipe2(2) returns success/failure; logs failure at debug level
Definition linux.hpp:299
Expected raise(int sig)
see raise(3) returns success/failure; logs failure at debug level
Definition linux.hpp:274
Expected< off_t > lseek(int fd, off_t offset, int whence)
see lseek(2) returns success/failure; logs failure at debug level
Definition linux.hpp:181
Expected< pid_t > getppid()
Definition linux.hpp:373
void(*)(int) SignalHandlerT
Definition linux.hpp:399
Expected< ssize_t > write(int fd, const std::string &data)
writes to a file descriptor. See write(2) returns success/failure; logs failure at debug level
Definition linux.hpp:45
Expected dup2(int oldfd, int newfd)
see dup(2) returns success/failure; logs failure at debug level
Definition linux.hpp:195
Expected< siginfo_t > waitid(idtype_t idtype, id_t id, int options=WSTOPPED|WEXITED)
see waitid(2) returns success/failure; logs failure at debug level
Definition linux.hpp:257
Expected< int > open(const std::string &pathname, int flags, mode_t mode=0)
see open(2) returns success/failure; logs failure at debug level
Definition linux.hpp:166
Expected< pid_t > getpid()
see getpid(2) and getppid(2) these functions "cannot fail" according to the manpage....
Definition linux.hpp:369
Expected< std::string > read(int fd, size_t count)
reads fromm a file descriptor. See read(2) returns success/failure; logs failure at debug level
Definition linux.hpp:60
Expected< int > fcntl(int fd, int cmd, std::optional< int > arg=std::nullopt)
see fcntl(2) returns success/failure; logs failure at debug level
Definition linux.hpp:233
std::error_code make_error_code(int err=errno)
Definition linux.hpp:39
Expected< int > ioctl(int fd, unsigned long request, void *argp)
see ioctl(2) returns success/failure; logs failure at debug level
Definition linux.hpp:216
Expected< struct ::stat > stat(const std::string &pathname)
see stat(2)
Definition linux.hpp:350
Expected execve(const std::string &exec, const std::vector< std::string > &args, const std::vector< std::string > &envp)
args and envp do NOT need to have an extra NULL element; this is added for you. see execve(2) returns...
Definition linux.hpp:111
Expected kill(pid_t pid, int sig)
see kill(2) returns success/failure; logs failure at debug level
Definition linux.hpp:95
Expected< SignalHandlerT > signal(Signal sig, SignalHandlerT handler)
Definition linux.hpp:401
Expected< long > ptrace(int request, pid_t pid=0, AddrT addr=NULL, DataT data=NULL)
see ptrace(2) returns success/failure; logs failure at debug level
Definition linux.hpp:322
Expected close(int fd)
closes a file descriptor. See close(2) returns success/failure; logs failure at debug level
Definition linux.hpp:80
std::string fmt_or_unknown(T &&value, fmt::fstring< T > fmt="{}")
Definition unknown.hpp:11
pid_t pid
Definition linux.hpp:143
@ Child
Definition linux.hpp:141
@ Parent
Definition linux.hpp:141
enum asmgrader::linux::Fork::@0 which
int write_fd
Definition linux.hpp:291
int read_fd
Definition linux.hpp:290