MimIR 0.1
MimIR is my Intermediate Representation
Loading...
Searching...
No Matches
sys.cpp
Go to the documentation of this file.
1#include "mim/util/sys.h"
2
3#include <algorithm>
4#include <array>
5#include <filesystem>
6#include <iostream>
7#include <vector>
8
9#include "mim/util/print.h"
10
11#ifdef _WIN32
12# include <windows.h>
13# define popen _popen
14# define pclose _pclose
15# define WEXITSTATUS
16#elif defined(__APPLE__)
17# include <mach-o/dyld.h>
18# include <unistd.h>
19#else
20# include <dlfcn.h>
21# include <unistd.h>
22#endif
23
24using namespace std::string_literals;
25
26namespace mim::sys {
27
28std::optional<fs::path> path_to_curr_exe() {
29 std::vector<char> path_buffer;
30#ifdef __APPLE__
31 uint32_t read = 0;
32 _NSGetExecutablePath(nullptr, &read); // get size
33 path_buffer.resize(read + 1);
34 if (_NSGetExecutablePath(path_buffer.data(), &read) != 0) return {};
35 return fs::path{path_buffer.data()};
36#elif defined(_WIN32)
37 size_t read = 0;
38 do {
39 // start with 256 (almost MAX_PATH) and grow exp
40 path_buffer.resize(std::max(path_buffer.size(), static_cast<size_t>(128)) * 2);
41 read = GetModuleFileNameA(nullptr, path_buffer.data(), static_cast<DWORD>(path_buffer.size()));
42 } while (read == path_buffer.size()); // if equal, the buffer was too small.
43
44 if (read != 0) {
45 path_buffer.resize(read + 1);
46 path_buffer.back() = 0;
47 return fs::path{path_buffer.data()};
48 }
49#else // Linux only..
50 if (fs::exists("/proc/self/exe")) return fs::canonical("/proc/self/exe");
51#endif // __APPLE__
52 return {};
53}
54
55// see https://stackoverflow.com/a/478960
56std::string exec(std::string cmd) {
57 std::array<char, 128> buffer;
58 std::string result;
59 std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd.c_str(), "r"), pclose);
60 if (!pipe) error("popen() failed!");
61 while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) result += buffer.data();
62 return result;
63}
64
65std::string find_cmd(std::string cmd) {
66 auto out = exec(MIM_WHICH " "s + cmd);
67 if (auto it = out.find('\n'); it != std::string::npos) out.erase(it);
68 return out;
69}
70
71int system(std::string cmd) {
72 std::cout << cmd << std::endl;
73 int status = std::system(cmd.c_str());
74 return WEXITSTATUS(status);
75}
76
77int run(std::string cmd, std::string args /* = {}*/) {
78#ifdef _WIN32
79 cmd += ".exe";
80#else
81 cmd = "./"s + cmd;
82#endif
83 return sys::system(cmd + " "s + args);
84}
85
86std::string escape(const std::filesystem::path& path) {
87 std::string str;
88 for (char c : path.string()) {
89 if (isspace(c)) str += '\\';
90 str += c;
91 }
92 return str;
93}
94
95} // namespace mim::sys
Definition sys.h:17
int run(std::string cmd, std::string args={})
Wraps sys::system and puts .exe at the back (Windows) and ./ at the front (otherwise) of cmd.
Definition sys.cpp:77
int system(std::string)
Wraps std::system and makes the return value usable.
Definition sys.cpp:71
std::optional< fs::path > path_to_curr_exe()
Yields std::nullopt if an error occurred.
Definition sys.cpp:28
std::string escape(const std::filesystem::path &path)
Returns the path as std::string and escapes all whitespaces with backslash.
Definition sys.cpp:86
std::string find_cmd(std::string)
Definition sys.cpp:65
std::string exec(std::string cmd)
Executes command cmd.
Definition sys.cpp:56
void error(Loc loc, const char *f, Args &&... args)
Definition dbg.h:122
#define MIM_WHICH
Definition sys.h:10