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