Repository navigation
Expand file tree
/
Copy pathEnvironment.cpp
More file actions
98 lines (92 loc) · 3.61 KB
/
Copy pathEnvironment.cpp
File metadata and controls
98 lines (92 loc) · 3.61 KB
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
#include <cstdlib>
#include <cerrno>
#include <cstring>
#include <algorithm>
#include <memory>
#include <mutex>
#include <string>
#include <string_view>
#include <vector>
#include "prx/libc/include/General.hpp"
#include "prx/libc/include/general/VabiMacros.hpp"
namespace {
struct EnvironmentEntry {
std::unique_ptr<std::string> owned;
char* borrowed = nullptr;
char* Data() { return borrowed ? borrowed : owned->data(); }
bool Matches(std::string_view name) {
const char* data = Data();
const char* separator = std::strchr(data, '=');
return separator && std::string_view(data, separator - data) == name;
}
};
std::mutex environmentMutex;
std::vector<EnvironmentEntry>& Environment() {
static std::vector<EnvironmentEntry> entries;
return entries;
}
bool ValidEnvironmentName(const char* name) {
return name && *name && !std::strchr(name, '=');
}
int EnvironmentError(int error) { errno = error; return -1; }
}
extern "C" {
bool CopyGuestEnvironment_nid_no_patch(const char* name, std::string& value) {
if (!ValidEnvironmentName(name)) return false;
std::lock_guard lock(environmentMutex);
for (auto& entry : Environment())
if (entry.Matches(name)) {
value = entry.Data() + std::strlen(name) + 1;
return true;
}
return false;
}
char* APS5_VABI getenv_nid_postfix(const char* name) {
if (!ValidEnvironmentName(name)) { errno = 22; return nullptr; }
try {
std::lock_guard lock(environmentMutex);
for (auto& entry : Environment())
if (entry.Matches(name)) return entry.Data() + std::strlen(name) + 1;
return nullptr;
} catch (const std::bad_alloc&) { errno = 12; return nullptr; }
}
int APS5_VABI setenv_nid_postfix(const char* name, const char* value, int overwrite) {
if (!ValidEnvironmentName(name) || !value) return EnvironmentError(22);
try {
std::lock_guard lock(environmentMutex);
auto& entries = Environment();
auto found = std::find_if(entries.begin(), entries.end(),
[name](auto& entry) { return entry.Matches(name); });
if (found != entries.end() && !overwrite) return 0;
EnvironmentEntry replacement{std::make_unique<std::string>(std::string(name) + '=' + value), nullptr};
if (found != entries.end()) *found = std::move(replacement);
else entries.push_back(std::move(replacement));
return 0;
} catch (const std::bad_alloc&) { return EnvironmentError(12); }
}
int APS5_VABI unsetenv_nid_postfix(const char* name) {
if (!ValidEnvironmentName(name)) return EnvironmentError(22);
try {
std::lock_guard lock(environmentMutex);
auto& entries = Environment();
const std::string key(name);
std::erase_if(entries, [&key](auto& entry) { return entry.Matches(key); });
return 0;
} catch (const std::bad_alloc&) { return EnvironmentError(12); }
}
int APS5_VABI putenv_nid_postfix(char* text) {
const char* separator = text ? std::strchr(text, '=') : nullptr;
if (!separator || separator == text) return EnvironmentError(22);
try {
std::lock_guard lock(environmentMutex);
auto& entries = Environment();
const std::string_view name(text, separator - text);
auto found = std::find_if(entries.begin(), entries.end(),
[name](auto& entry) { return entry.Matches(name); });
EnvironmentEntry replacement{nullptr, text};
if (found != entries.end()) *found = std::move(replacement);
else entries.push_back(std::move(replacement));
return 0;
} catch (const std::bad_alloc&) { return EnvironmentError(12); }
}
}