Chris@223
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
Chris@223
|
2
|
Chris@223
|
3 /*
|
Chris@1356
|
4 Sonic Visualiser
|
Chris@1356
|
5 An audio file viewer and annotation editor.
|
Chris@1356
|
6 Centre for Digital Music, Queen Mary, University of London.
|
Chris@1475
|
7 This file copyright 2006-2018 Chris Cannam and QMUL.
|
Chris@223
|
8
|
Chris@1356
|
9 This program is free software; you can redistribute it and/or
|
Chris@1356
|
10 modify it under the terms of the GNU General Public License as
|
Chris@1356
|
11 published by the Free Software Foundation; either version 2 of the
|
Chris@1356
|
12 License, or (at your option) any later version. See the file
|
Chris@1356
|
13 COPYING included with this distribution for more information.
|
Chris@223
|
14 */
|
Chris@223
|
15
|
Chris@223
|
16 #include "System.h"
|
Chris@223
|
17
|
Chris@223
|
18 #include <QStringList>
|
Chris@223
|
19 #include <QString>
|
Chris@223
|
20
|
Chris@223
|
21 #include <stdint.h>
|
Chris@223
|
22
|
Chris@223
|
23 #ifndef _WIN32
|
Chris@223
|
24 #include <signal.h>
|
Chris@223
|
25 #include <sys/statvfs.h>
|
Chris@608
|
26 #include <locale.h>
|
Chris@608
|
27 #include <unistd.h>
|
Chris@223
|
28 #endif
|
Chris@223
|
29
|
Chris@1825
|
30 #ifndef AVOID_WINRT_DEPENDENCY
|
Chris@1818
|
31 #ifdef _MSC_VER
|
Chris@1818
|
32 #include <winrt/Windows.UI.ViewManagement.h>
|
Chris@1818
|
33 #endif
|
Chris@1825
|
34 #endif
|
Chris@1818
|
35
|
Chris@223
|
36 #ifdef __APPLE__
|
Chris@223
|
37 #include <sys/param.h>
|
Chris@223
|
38 #include <sys/sysctl.h>
|
Chris@223
|
39 #endif
|
Chris@223
|
40
|
Chris@405
|
41 #include <limits.h>
|
Chris@405
|
42 #include <cstdlib>
|
Chris@405
|
43
|
Chris@223
|
44 #include <iostream>
|
Chris@223
|
45
|
Chris@255
|
46 #ifdef __APPLE__
|
Chris@255
|
47 extern "C" {
|
Chris@1356
|
48 void *
|
Chris@1356
|
49 rpl_realloc (void *p, size_t n)
|
Chris@255
|
50 {
|
Chris@1356
|
51 p = realloc(p, n);
|
Chris@1356
|
52 if (p == 0 && n == 0)
|
Chris@1356
|
53 {
|
Chris@1356
|
54 p = malloc(0);
|
Chris@1356
|
55 }
|
Chris@1356
|
56 return p;
|
Chris@255
|
57 }
|
Chris@255
|
58 }
|
Chris@255
|
59 #endif
|
Chris@255
|
60
|
Chris@223
|
61 #ifdef _WIN32
|
Chris@223
|
62
|
Chris@223
|
63 extern "C" {
|
Chris@223
|
64
|
Chris@1218
|
65 #ifdef _MSC_VER
|
Chris@1356
|
66 void usleep(unsigned long usec)
|
Chris@1356
|
67 {
|
Chris@1356
|
68 ::Sleep(usec / 1000);
|
Chris@1356
|
69 }
|
Chris@1218
|
70 #endif
|
Chris@223
|
71
|
Chris@1475
|
72 int gettimeofday(struct timeval *tv, void * /* tz */)
|
Chris@1356
|
73 {
|
Chris@1356
|
74 union {
|
Chris@1356
|
75 long long ns100;
|
Chris@1356
|
76 FILETIME ft;
|
Chris@1356
|
77 } now;
|
Chris@223
|
78
|
Chris@1356
|
79 ::GetSystemTimeAsFileTime(&now.ft);
|
Chris@1356
|
80 tv->tv_usec = (long)((now.ns100 / 10LL) % 1000000LL);
|
Chris@1356
|
81 tv->tv_sec = (long)((now.ns100 - 116444736000000000LL) / 10000000LL);
|
Chris@1356
|
82 return 0;
|
Chris@1356
|
83 }
|
Chris@223
|
84
|
Chris@223
|
85 }
|
Chris@223
|
86
|
Chris@223
|
87 #endif
|
Chris@223
|
88
|
Chris@223
|
89 ProcessStatus
|
Chris@223
|
90 GetProcessStatus(int pid)
|
Chris@223
|
91 {
|
Chris@223
|
92 #ifdef _WIN32
|
Chris@223
|
93 HANDLE handle = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
|
Chris@223
|
94 if (!handle) {
|
Chris@223
|
95 return ProcessNotRunning;
|
Chris@223
|
96 } else {
|
Chris@223
|
97 CloseHandle(handle);
|
Chris@223
|
98 return ProcessRunning;
|
Chris@223
|
99 }
|
Chris@223
|
100 #else
|
Chris@223
|
101 if (kill(getpid(), 0) == 0) {
|
Chris@223
|
102 if (kill(pid, 0) == 0) {
|
Chris@223
|
103 return ProcessRunning;
|
Chris@223
|
104 } else {
|
Chris@223
|
105 return ProcessNotRunning;
|
Chris@223
|
106 }
|
Chris@223
|
107 } else {
|
Chris@223
|
108 return UnknownProcessStatus;
|
Chris@223
|
109 }
|
Chris@223
|
110 #endif
|
Chris@223
|
111 }
|
Chris@223
|
112
|
Chris@223
|
113 #ifdef _WIN32
|
Chris@223
|
114 /* MEMORYSTATUSEX is missing from older Windows headers, so define a
|
Chris@223
|
115 local replacement. This trick from MinGW source code. Ugh */
|
Chris@223
|
116 typedef struct
|
Chris@223
|
117 {
|
Chris@223
|
118 DWORD dwLength;
|
Chris@223
|
119 DWORD dwMemoryLoad;
|
Chris@223
|
120 DWORDLONG ullTotalPhys;
|
Chris@223
|
121 DWORDLONG ullAvailPhys;
|
Chris@223
|
122 DWORDLONG ullTotalPageFile;
|
Chris@223
|
123 DWORDLONG ullAvailPageFile;
|
Chris@223
|
124 DWORDLONG ullTotalVirtual;
|
Chris@223
|
125 DWORDLONG ullAvailVirtual;
|
Chris@223
|
126 DWORDLONG ullAvailExtendedVirtual;
|
Chris@223
|
127 } lMEMORYSTATUSEX;
|
Chris@1218
|
128 typedef BOOL (WINAPI *PFN_MS_EX) (lMEMORYSTATUSEX*);
|
Chris@223
|
129 #endif
|
Chris@223
|
130
|
Chris@223
|
131 void
|
Chris@1038
|
132 GetRealMemoryMBAvailable(ssize_t &available, ssize_t &total)
|
Chris@223
|
133 {
|
Chris@223
|
134 available = -1;
|
Chris@223
|
135 total = -1;
|
Chris@223
|
136
|
Chris@223
|
137 #ifdef _WIN32
|
Chris@223
|
138
|
Chris@223
|
139 static bool checked = false;
|
Chris@223
|
140 static bool exFound = false;
|
Chris@223
|
141 static PFN_MS_EX ex;
|
Chris@223
|
142
|
Chris@223
|
143 if (!checked) {
|
Chris@223
|
144
|
Chris@223
|
145 HMODULE h = GetModuleHandleA("kernel32.dll");
|
Chris@223
|
146
|
Chris@223
|
147 if (h) {
|
Chris@223
|
148 if ((ex = (PFN_MS_EX)GetProcAddress(h, "GlobalMemoryStatusEx"))) {
|
Chris@223
|
149 exFound = true;
|
Chris@223
|
150 }
|
Chris@223
|
151 }
|
Chris@223
|
152
|
Chris@223
|
153 checked = true;
|
Chris@223
|
154 }
|
Chris@223
|
155
|
Chris@223
|
156 DWORDLONG wavail = 0;
|
Chris@223
|
157 DWORDLONG wtotal = 0;
|
Chris@223
|
158
|
Chris@223
|
159 if (exFound) {
|
Chris@223
|
160
|
Chris@223
|
161 lMEMORYSTATUSEX lms;
|
Chris@1356
|
162 lms.dwLength = sizeof(lms);
|
Chris@1356
|
163 if (!ex(&lms)) {
|
Chris@843
|
164 cerr << "WARNING: GlobalMemoryStatusEx failed: error code "
|
Chris@1356
|
165 << GetLastError() << endl;
|
Chris@223
|
166 return;
|
Chris@223
|
167 }
|
Chris@223
|
168 wavail = lms.ullAvailPhys;
|
Chris@223
|
169 wtotal = lms.ullTotalPhys;
|
Chris@223
|
170
|
Chris@223
|
171 } else {
|
Chris@223
|
172
|
Chris@223
|
173 /* Fall back to GlobalMemoryStatus which is always available.
|
Chris@223
|
174 but returns wrong results for physical memory > 4GB */
|
Chris@223
|
175
|
Chris@1356
|
176 MEMORYSTATUS ms;
|
Chris@1356
|
177 GlobalMemoryStatus(&ms);
|
Chris@1356
|
178 wavail = ms.dwAvailPhys;
|
Chris@223
|
179 wtotal = ms.dwTotalPhys;
|
Chris@223
|
180 }
|
Chris@223
|
181
|
Chris@223
|
182 DWORDLONG size = wavail / 1048576;
|
Chris@223
|
183 if (size > INT_MAX) size = INT_MAX;
|
Chris@1038
|
184 available = ssize_t(size);
|
Chris@223
|
185
|
Chris@223
|
186 size = wtotal / 1048576;
|
Chris@223
|
187 if (size > INT_MAX) size = INT_MAX;
|
Chris@1038
|
188 total = ssize_t(size);
|
Chris@223
|
189
|
Chris@223
|
190 return;
|
Chris@223
|
191
|
Chris@223
|
192 #else
|
Chris@223
|
193 #ifdef __APPLE__
|
Chris@223
|
194
|
Chris@1779
|
195 unsigned int val32;
|
Chris@1779
|
196 int64_t val64;
|
Chris@223
|
197 int mib[2];
|
Chris@223
|
198 size_t size_sys;
|
Chris@223
|
199
|
Chris@223
|
200 mib[0] = CTL_HW;
|
Chris@223
|
201
|
Chris@1779
|
202 mib[1] = HW_MEMSIZE;
|
Chris@1779
|
203 size_sys = sizeof(val64);
|
Chris@1779
|
204 sysctl(mib, 2, &val64, &size_sys, NULL, 0);
|
Chris@1779
|
205 if (val64) total = val64 / 1048576;
|
Chris@223
|
206
|
Chris@223
|
207 mib[1] = HW_USERMEM;
|
Chris@1779
|
208 size_sys = sizeof(val32);
|
Chris@1779
|
209 sysctl(mib, 2, &val32, &size_sys, NULL, 0);
|
Chris@1779
|
210 if (val32) available = val32 / 1048576;
|
Chris@1779
|
211
|
Chris@1779
|
212 // The newer memsize sysctl returns a 64-bit value, but usermem is
|
Chris@1779
|
213 // an old 32-bit value that doesn't seem to have an updated
|
Chris@1779
|
214 // alternative (?) - so it can't return more than 2G. In practice
|
Chris@1779
|
215 // it seems to return values far lower than that, even where more
|
Chris@1779
|
216 // than 2G of real memory is free. So we can't actually tell when
|
Chris@1779
|
217 // we're getting low on memory at all. Most of the time I think we
|
Chris@1779
|
218 // just need to use an arbitrary value like this one.
|
Chris@1779
|
219 if (available < total/4) {
|
Chris@1779
|
220 available = total/4;
|
Chris@1779
|
221 }
|
Chris@223
|
222
|
Chris@223
|
223 return;
|
Chris@223
|
224
|
Chris@223
|
225 #else
|
Chris@223
|
226
|
Chris@223
|
227 FILE *meminfo = fopen("/proc/meminfo", "r");
|
Chris@223
|
228 if (!meminfo) return;
|
Chris@223
|
229
|
Chris@223
|
230 char buf[256];
|
Chris@223
|
231 while (!feof(meminfo)) {
|
Chris@1363
|
232 if (!fgets(buf, 256, meminfo)) {
|
Chris@1424
|
233 fclose(meminfo);
|
Chris@1363
|
234 return;
|
Chris@1363
|
235 }
|
Chris@223
|
236 bool isMemFree = (strncmp(buf, "MemFree:", 8) == 0);
|
Chris@223
|
237 bool isMemTotal = (!isMemFree && (strncmp(buf, "MemTotal:", 9) == 0));
|
Chris@223
|
238 if (isMemFree || isMemTotal) {
|
Chris@223
|
239 QString line = QString(buf).trimmed();
|
Chris@223
|
240 QStringList elements = line.split(' ', QString::SkipEmptyParts);
|
Chris@223
|
241 QString unit = "kB";
|
Chris@223
|
242 if (elements.size() > 2) unit = elements[2];
|
Chris@223
|
243 int size = elements[1].toInt();
|
Chris@843
|
244 // cerr << "have size \"" << size << "\", unit \""
|
Chris@843
|
245 // << unit << "\"" << endl;
|
Chris@223
|
246 if (unit.toLower() == "gb") size = size * 1024;
|
Chris@223
|
247 else if (unit.toLower() == "mb") size = size;
|
Chris@223
|
248 else if (unit.toLower() == "kb") size = size / 1024;
|
Chris@223
|
249 else size = size / 1048576;
|
Chris@223
|
250
|
Chris@223
|
251 if (isMemFree) available = size;
|
Chris@223
|
252 else total = size;
|
Chris@223
|
253 }
|
Chris@223
|
254 if (available != -1 && total != -1) {
|
Chris@223
|
255 fclose(meminfo);
|
Chris@223
|
256 return;
|
Chris@223
|
257 }
|
Chris@223
|
258 }
|
Chris@223
|
259 fclose(meminfo);
|
Chris@223
|
260
|
Chris@223
|
261 return;
|
Chris@223
|
262
|
Chris@223
|
263 #endif
|
Chris@223
|
264 #endif
|
Chris@223
|
265 }
|
Chris@223
|
266
|
Chris@1038
|
267 ssize_t
|
Chris@223
|
268 GetDiscSpaceMBAvailable(const char *path)
|
Chris@223
|
269 {
|
Chris@223
|
270 #ifdef _WIN32
|
Chris@223
|
271 ULARGE_INTEGER available, total, totalFree;
|
Chris@223
|
272 if (GetDiskFreeSpaceExA(path, &available, &total, &totalFree)) {
|
Chris@1356
|
273 __int64 a = available.QuadPart;
|
Chris@223
|
274 a /= 1048576;
|
Chris@223
|
275 if (a > INT_MAX) a = INT_MAX;
|
Chris@1038
|
276 return ssize_t(a);
|
Chris@223
|
277 } else {
|
Chris@843
|
278 cerr << "WARNING: GetDiskFreeSpaceEx failed: error code "
|
Chris@1356
|
279 << GetLastError() << endl;
|
Chris@223
|
280 return -1;
|
Chris@223
|
281 }
|
Chris@223
|
282 #else
|
Chris@223
|
283 struct statvfs buf;
|
Chris@223
|
284 if (!statvfs(path, &buf)) {
|
Chris@223
|
285 // do the multiplies and divides in this order to reduce the
|
Chris@223
|
286 // likelihood of arithmetic overflow
|
Chris@843
|
287 // cerr << "statvfs(" << path << ") says available: " << buf.f_bavail << ", block size: " << buf.f_bsize << endl;
|
Chris@223
|
288 uint64_t available = ((buf.f_bavail / 1024) * buf.f_bsize) / 1024;
|
Chris@223
|
289 if (available > INT_MAX) available = INT_MAX;
|
Chris@1038
|
290 return ssize_t(available);
|
Chris@223
|
291 } else {
|
Chris@223
|
292 perror("statvfs failed");
|
Chris@223
|
293 return -1;
|
Chris@223
|
294 }
|
Chris@223
|
295 #endif
|
Chris@223
|
296 }
|
Chris@303
|
297
|
Chris@835
|
298 #ifdef _WIN32
|
Chris@835
|
299 extern void SystemMemoryBarrier()
|
Chris@835
|
300 {
|
Chris@1218
|
301 #ifdef _MSC_VER
|
Chris@835
|
302 MemoryBarrier();
|
Chris@835
|
303 #else /* mingw */
|
Chris@835
|
304 LONG Barrier = 0;
|
Chris@835
|
305 __asm__ __volatile__("xchgl %%eax,%0 "
|
Chris@835
|
306 : "=r" (Barrier));
|
Chris@835
|
307 #endif
|
Chris@835
|
308 }
|
Chris@835
|
309 #else /* !_WIN32 */
|
Chris@1357
|
310 #if !defined(__APPLE__) && defined(__GNUC__) && ((__GNUC__ < 4) || (__GNUC__ == 4 && __GNUC_MINOR__ == 0))
|
Chris@835
|
311 void
|
Chris@835
|
312 SystemMemoryBarrier()
|
Chris@835
|
313 {
|
Chris@835
|
314 pthread_mutex_t dummy = PTHREAD_MUTEX_INITIALIZER;
|
Chris@835
|
315 pthread_mutex_lock(&dummy);
|
Chris@835
|
316 pthread_mutex_unlock(&dummy);
|
Chris@835
|
317 }
|
Chris@835
|
318 #endif /* !defined(__APPLE__) etc */
|
Chris@835
|
319 #endif /* !_WIN32 */
|
Chris@835
|
320
|
Chris@835
|
321
|
Chris@1582
|
322 static char *startupLocale = nullptr;
|
Chris@303
|
323
|
Chris@303
|
324 void
|
Chris@303
|
325 StoreStartupLocale()
|
Chris@303
|
326 {
|
Chris@1582
|
327 char *loc = setlocale(LC_ALL, nullptr);
|
Chris@303
|
328 if (!loc) return;
|
Chris@303
|
329 if (startupLocale) free(startupLocale);
|
Chris@303
|
330 startupLocale = strdup(loc);
|
Chris@303
|
331 }
|
Chris@303
|
332
|
Chris@303
|
333 void
|
Chris@303
|
334 RestoreStartupLocale()
|
Chris@303
|
335 {
|
Chris@303
|
336 if (!startupLocale) {
|
Chris@303
|
337 setlocale(LC_ALL, "");
|
Chris@303
|
338 } else {
|
Chris@303
|
339 setlocale(LC_ALL, startupLocale);
|
Chris@303
|
340 }
|
Chris@303
|
341 }
|
Chris@223
|
342
|
Chris@1818
|
343 bool
|
Chris@1819
|
344 OSReportsDarkThemeActive()
|
Chris@1818
|
345 {
|
Chris@1819
|
346 SVCERR << "OSReportsDarkThemeActive() called" << endl;
|
Chris@1825
|
347 #ifndef AVOID_WINRT_DEPENDENCY
|
Chris@1818
|
348 #ifdef _MSC_VER
|
Chris@1818
|
349 using namespace winrt::Windows::UI::ViewManagement;
|
Chris@1818
|
350 UISettings settings;
|
Chris@1818
|
351 auto background = settings.GetColorValue(UIColorType::Background);
|
Chris@1818
|
352 if (int(background.R) + int(background.G) + int(background.B) < 384) {
|
Chris@1818
|
353 return true;
|
Chris@1818
|
354 }
|
Chris@1818
|
355 #endif
|
Chris@1825
|
356 #endif
|
Chris@1818
|
357 return false;
|
Chris@1818
|
358 }
|
Chris@1818
|
359
|
Chris@1820
|
360 bool
|
Chris@1820
|
361 OSQueryAccentColour(int &r, int &g, int &b)
|
Chris@1820
|
362 {
|
Chris@1820
|
363 SVCERR << "OSQueryAccentColour() called" << endl;
|
Chris@1825
|
364 #ifndef AVOID_WINRT_DEPENDENCY
|
Chris@1820
|
365 #ifdef _MSC_VER
|
Chris@1820
|
366 using namespace winrt::Windows::UI::ViewManagement;
|
Chris@1821
|
367 bool dark = OSReportsDarkThemeActive();
|
Chris@1820
|
368 UISettings settings;
|
Chris@1821
|
369 auto accent = settings.GetColorValue
|
Chris@1821
|
370 (dark ? UIColorType::AccentLight1 : UIColorType::Accent);
|
Chris@1821
|
371 r = accent.R;
|
Chris@1821
|
372 g = accent.G;
|
Chris@1821
|
373 b = accent.B;
|
Chris@1820
|
374 return true;
|
Chris@1820
|
375 #endif
|
Chris@1825
|
376 #endif
|
Chris@1820
|
377 return false;
|
Chris@1820
|
378 }
|
Chris@1820
|
379
|
Chris@223
|
380 double mod(double x, double y) { return x - (y * floor(x / y)); }
|
Chris@223
|
381 float modf(float x, float y) { return x - (y * floorf(x / y)); }
|
Chris@223
|
382
|
Chris@223
|
383 double princarg(double a) { return mod(a + M_PI, -2 * M_PI) + M_PI; }
|
Chris@1039
|
384 float princargf(float a) { return float(princarg(a)); }
|
Chris@223
|
385
|
Chris@1475
|
386 bool
|
Chris@1475
|
387 getEnvUtf8(std::string variable, std::string &value)
|
Chris@1475
|
388 {
|
Chris@1475
|
389 value = "";
|
Chris@1475
|
390
|
Chris@1475
|
391 #ifdef _WIN32
|
Chris@1475
|
392 int wvarlen = MultiByteToWideChar(CP_UTF8, 0,
|
Chris@1475
|
393 variable.c_str(), int(variable.length()),
|
Chris@1475
|
394 0, 0);
|
Chris@1475
|
395 if (wvarlen < 0) {
|
Chris@1475
|
396 SVCERR << "WARNING: Unable to convert environment variable name "
|
Chris@1475
|
397 << variable << " to wide characters" << endl;
|
Chris@1475
|
398 return false;
|
Chris@1475
|
399 }
|
Chris@1475
|
400
|
Chris@1475
|
401 wchar_t *wvarbuf = new wchar_t[wvarlen + 1];
|
Chris@1475
|
402 (void)MultiByteToWideChar(CP_UTF8, 0,
|
Chris@1475
|
403 variable.c_str(), int(variable.length()),
|
Chris@1475
|
404 wvarbuf, wvarlen);
|
Chris@1475
|
405 wvarbuf[wvarlen] = L'\0';
|
Chris@1475
|
406
|
Chris@1475
|
407 wchar_t *wvalue = _wgetenv(wvarbuf);
|
Chris@1176
|
408
|
Chris@1475
|
409 delete[] wvarbuf;
|
Chris@1475
|
410
|
Chris@1475
|
411 if (!wvalue) {
|
Chris@1475
|
412 return false;
|
Chris@1475
|
413 }
|
Chris@1475
|
414
|
Chris@1480
|
415 int wvallen = int(wcslen(wvalue));
|
Chris@1475
|
416 int vallen = WideCharToMultiByte(CP_UTF8, 0,
|
Chris@1480
|
417 wvalue, wvallen,
|
Chris@1475
|
418 0, 0, 0, 0);
|
Chris@1475
|
419 if (vallen < 0) {
|
Chris@1475
|
420 SVCERR << "WARNING: Unable to convert environment value to UTF-8"
|
Chris@1475
|
421 << endl;
|
Chris@1475
|
422 return false;
|
Chris@1475
|
423 }
|
Chris@1475
|
424
|
Chris@1475
|
425 char *val = new char[vallen + 1];
|
Chris@1475
|
426 (void)WideCharToMultiByte(CP_UTF8, 0,
|
Chris@1480
|
427 wvalue, wvallen,
|
Chris@1475
|
428 val, vallen, 0, 0);
|
Chris@1475
|
429 val[vallen] = '\0';
|
Chris@1475
|
430
|
Chris@1475
|
431 value = val;
|
Chris@1475
|
432
|
Chris@1475
|
433 delete[] val;
|
Chris@1475
|
434 return true;
|
Chris@1475
|
435
|
Chris@1475
|
436 #else
|
Chris@1475
|
437
|
Chris@1475
|
438 char *val = getenv(variable.c_str());
|
Chris@1475
|
439 if (!val) {
|
Chris@1475
|
440 return false;
|
Chris@1475
|
441 }
|
Chris@1475
|
442
|
Chris@1475
|
443 value = val;
|
Chris@1475
|
444 return true;
|
Chris@1475
|
445
|
Chris@1475
|
446 #endif
|
Chris@1475
|
447 }
|
Chris@1475
|
448
|
Chris@1475
|
449 bool
|
Chris@1475
|
450 putEnvUtf8(std::string variable, std::string value)
|
Chris@1475
|
451 {
|
Chris@1477
|
452 #ifdef _WIN32
|
Chris@1475
|
453 std::string entry = variable + "=" + value;
|
Chris@1475
|
454
|
Chris@1475
|
455 int wentlen = MultiByteToWideChar(CP_UTF8, 0,
|
Chris@1475
|
456 entry.c_str(), int(entry.length()),
|
Chris@1475
|
457 0, 0);
|
Chris@1475
|
458 if (wentlen < 0) {
|
Chris@1475
|
459 SVCERR << "WARNING: Unable to convert environment entry to "
|
Chris@1475
|
460 << "wide characters" << endl;
|
Chris@1475
|
461 return false;
|
Chris@1475
|
462 }
|
Chris@1475
|
463
|
Chris@1475
|
464 wchar_t *wentbuf = new wchar_t[wentlen + 1];
|
Chris@1475
|
465 (void)MultiByteToWideChar(CP_UTF8, 0,
|
Chris@1475
|
466 entry.c_str(), int(entry.length()),
|
Chris@1475
|
467 wentbuf, wentlen);
|
Chris@1475
|
468 wentbuf[wentlen] = L'\0';
|
Chris@1475
|
469
|
Chris@1475
|
470 int rv = _wputenv(wentbuf);
|
Chris@1475
|
471
|
Chris@1475
|
472 delete[] wentbuf;
|
Chris@1475
|
473
|
Chris@1475
|
474 if (rv != 0) {
|
Chris@1475
|
475 SVCERR << "WARNING: Failed to set environment entry" << endl;
|
Chris@1475
|
476 return false;
|
Chris@1475
|
477 }
|
Chris@1475
|
478 return true;
|
Chris@1475
|
479
|
Chris@1475
|
480 #else
|
Chris@1475
|
481
|
Chris@1477
|
482 int rv = setenv(variable.c_str(), value.c_str(), 1);
|
Chris@1475
|
483 if (rv != 0) {
|
Chris@1475
|
484 SVCERR << "WARNING: Failed to set environment entry" << endl;
|
Chris@1475
|
485 return false;
|
Chris@1475
|
486 }
|
Chris@1475
|
487 return true;
|
Chris@1475
|
488
|
Chris@1475
|
489 #endif
|
Chris@1475
|
490 }
|
Chris@1475
|
491
|