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 using PipeCloser = int (*)(FILE*); // spell out type explicitly to get rid of warning
58 if (auto pipe = std::unique_ptr<FILE, PipeCloser>(popen(cmd.c_str(), "r"), pclose)) {
59 std::array<char, 128> buffer;
60 std::string result;
61 while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr)
62 result += buffer.data();
63 return result;
64 } else
65 error("popen() failed!");
66}
67
68std::string find_cmd(std::string cmd) {
69 auto out = exec(MIM_WHICH " "s + cmd);
70 if (auto it = out.find('\n'); it != std::string::npos) out.erase(it);
71 return out;
72}
73
74int system(std::string cmd) {
75 std::cout << cmd << std::endl;
76 int status = std::system(cmd.c_str());
77 return WEXITSTATUS(status);
78}
79
80int run(std::string cmd, std::string args /* = {}*/) {
81#ifdef _WIN32
82 cmd += ".exe";
83#else
84 cmd = "./"s + cmd;
85#endif
86 return sys::system(cmd + " "s + args);
87}
88
89std::string escape(const std::filesystem::path& path) {
90 std::string str;
91 for (char c : path.string()) {
92 if (isspace(c)) str += '\\';
93 str += c;
94 }
95 return str;
96}
97
98} // 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:80
int system(std::string)
Wraps std::system and makes the return value usable.
Definition sys.cpp:74
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:89
std::string find_cmd(std::string)
Definition sys.cpp:68
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:125
#define MIM_WHICH
Definition sys.h:10