-
-
Notifications
You must be signed in to change notification settings - Fork 56
Expand file tree
/
Copy pathcstdlib.cpp
More file actions
162 lines (144 loc) · 4.35 KB
/
Copy pathcstdlib.cpp
File metadata and controls
162 lines (144 loc) · 4.35 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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
//
// Copyright (c) 2012 Artyom Beilis (Tonkikh)
// Copyright (c) 2020-2022 Alexander Grund
//
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#define BOOST_NOWIDE_SOURCE
#ifdef _MSC_VER
#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#endif
#elif defined(__MINGW32__) && defined(__STRICT_ANSI__)
// Need the _w* functions which are extensions on MinGW but not on MinGW-w64
#include <_mingw.h>
#ifndef __MINGW64_VERSION_MAJOR
#undef __STRICT_ANSI__
#endif
#elif defined(__CYGWIN__) && !defined(_GNU_SOURCE)
// The setenv family of functions is an extension on Cygwin
#define _GNU_SOURCE 1
#endif
#include <boost/nowide/cstdlib.hpp>
#ifndef BOOST_WINDOWS
namespace boost {
namespace nowide {
int setenv(const char* key, const char* value, int overwrite)
{
return ::setenv(key, value, overwrite);
}
int unsetenv(const char* key)
{
return ::unsetenv(key);
}
int putenv(char* string)
{
return ::putenv(string);
}
} // namespace nowide
} // namespace boost
#else
#include <boost/nowide/stackstring.hpp>
#include <vector>
#include <windows.h>
namespace {
// thread_local was broken on MinGW for all 32bit compiler releases prior to 11.x, see
// https://sourceforge.net/p/mingw-w64/bugs/527/
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83562
// Using a non-trivial destructor causes program termination on thread exit.
#if defined(__MINGW32__) && !defined(__MINGW64__) && !defined(__clang__) && (__GNUC__ < 11)
class stackstring_for_thread
{
union
{
boost::nowide::stackstring s_;
};
public:
stackstring_for_thread() : s_(){};
// Empty destructor so the union member (using a non-trivial destructor) does not get destroyed.
// This will leak memory if any is allocated by the stackstring for each terminated thread
// but as most values fit into the stack buffer this is rare and still better than a crash.
~stackstring_for_thread(){};
void convert(const wchar_t* begin, const wchar_t* end)
{
s_.convert(begin, end);
}
char* get()
{
return s_.get();
}
};
#else
using stackstring_for_thread = boost::nowide::stackstring;
#endif
} // namespace
namespace boost {
namespace nowide {
char* getenv(const char* key)
{
thread_local stackstring_for_thread value;
const wshort_stackstring name(key);
static const size_t buf_size = 64;
wchar_t buf[buf_size];
std::vector<wchar_t> tmp;
wchar_t* ptr = buf;
size_t n = GetEnvironmentVariableW(name.get(), buf, buf_size);
if(n == 0 && GetLastError() == 203) // ERROR_ENVVAR_NOT_FOUND
return 0;
if(n >= buf_size)
{
tmp.resize(n + 1, L'\0');
n = GetEnvironmentVariableW(name.get(), &tmp[0], static_cast<unsigned>(tmp.size() - 1));
// The size may have changed
if(n >= tmp.size() - 1)
return 0;
ptr = &tmp[0];
}
value.convert(ptr, ptr + n);
return value.get();
}
int setenv(const char* key, const char* value, int overwrite)
{
const wshort_stackstring name(key);
if(!overwrite)
{
wchar_t unused[2];
if(GetEnvironmentVariableW(name.get(), unused, 2) != 0 || GetLastError() != 203) // ERROR_ENVVAR_NOT_FOUND
return 0;
}
const wstackstring wval(value);
if(SetEnvironmentVariableW(name.get(), wval.get()))
return 0;
return -1;
}
int unsetenv(const char* key)
{
const wshort_stackstring name(key);
if(SetEnvironmentVariableW(name.get(), 0))
return 0;
return -1;
}
int putenv(char* string)
{
const char* key = string;
const char* key_end = string;
while(*key_end != '=' && *key_end != '\0')
key_end++;
if(*key_end == '\0')
return -1;
const wshort_stackstring wkey(key, key_end);
const wstackstring wvalue(key_end + 1);
if(SetEnvironmentVariableW(wkey.get(), wvalue.get()))
return 0;
return -1;
}
int system(const char* cmd)
{
if(!cmd)
return _wsystem(0);
const wstackstring wcmd(cmd);
return _wsystem(wcmd.get());
}
} // namespace nowide
} // namespace boost
#endif