-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathenv.cpp
More file actions
82 lines (69 loc) · 2.93 KB
/
Copy pathenv.cpp
File metadata and controls
82 lines (69 loc) · 2.93 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
#include "sys.h"
#include <openkal/env.h>
namespace okm {
// The vectors this system passes to a program's entry point. They are recorded
// by whichever of the two entrances the program has: this implementation's own
// entry, when the program carries no other runtime, and otherwise an
// initialiser, which this system calls with the same three arguments.
int g_argc = 0;
char** g_argv = nullptr;
char** g_envp = nullptr;
void record(int argc, char** argv, char** envp) {
g_argc = argc; g_argv = argv; g_envp = envp;
}
} // namespace okm
namespace {
[[gnu::constructor(101)]] void capture(int argc, char** argv, char** envp) {
if (okm::g_argv == nullptr) okm::record(argc, argv, envp);
}
} // namespace
extern "C" {
kal_uintptr kal_env_arg_count(void) { return static_cast<kal_uintptr>(okm::g_argc); }
// EVERY VALUE IS COPIED INTO THE CALLER'S BUFFER. These answered with a pointer
// into this implementation's own storage, which is meaningful only while the
// implementation shares the caller's address space. Each reports the length the
// value HAS, so a caller with a large enough buffer is done in one call and one
// that wants to size first passes a capacity of zero.
namespace {
kal_intptr give(const char* v, kal_uintptr n, char* out, kal_uintptr cap) {
if (out != nullptr && cap != 0) okm::copy(out, v, n < cap ? n : cap);
return static_cast<kal_intptr>(n);
}
} // namespace
kal_intptr kal_env_arg(kal_uintptr index, char* out, kal_uintptr cap) {
if (index >= static_cast<kal_uintptr>(okm::g_argc)) return -kal_err_not_found;
const char* s = okm::g_argv[index];
return give(s, okm::length(s), out, cap);
}
kal_intptr kal_env_var(const char* name, kal_uintptr name_len,
char* out, kal_uintptr cap) {
if (name == nullptr) return -kal_err_invalid;
for (char** e = okm::g_envp; e && *e; ++e) {
const char* entry = *e;
kal_uintptr i = 0;
while (i < name_len && entry[i] != '\0' && entry[i] == name[i]) ++i;
if (i == name_len && entry[i] == '=') {
const char* v = entry + name_len + 1;
return give(v, okm::length(v), out, cap);
}
}
// A name that is not there is distinct from one whose value is empty.
return -kal_err_not_found;
}
kal_uintptr kal_env_var_count(void) {
kal_uintptr n = 0; for (char** e = okm::g_envp; e && *e; ++e) ++n; return n;
}
// The NAME at a position. The value is then obtained by kal_env_var: an
// operation answering both needs two buffers, two capacities and two lengths,
// and its second half is kal_env_var written again.
kal_intptr kal_env_var_at(kal_uintptr index, char* out, kal_uintptr cap) {
kal_uintptr n = 0;
for (char** e = okm::g_envp; e && *e; ++e, ++n) {
if (n != index) continue;
const char* entry = *e;
kal_uintptr i = 0; while (entry[i] != '\0' && entry[i] != '=') ++i;
return give(entry, i, out, cap);
}
return -kal_err_not_found;
}
}