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