GCC Code Coverage Report


Directory: src/gate/
File: src/gate/environments.c
Date: 2025-12-12 23:40:09
Exec Total Coverage
Lines: 172 247 69.6%
Functions: 19 22 86.4%
Branches: 52 122 42.6%

Line Branch Exec Source
1 /* GATE PROJECT LICENSE:
2 +----------------------------------------------------------------------------+
3 | Copyright(c) 2018-2025, Stefan Meislinger <sm@opengate.at> |
4 | All rights reserved. |
5 | |
6 | Redistribution and use in source and binary forms, with or without |
7 | modification, are permitted provided that the following conditions are met:|
8 | |
9 | 1. Redistributions of source code must retain the above copyright notice, |
10 | this list of conditions and the following disclaimer. |
11 | 2. Redistributions in binary form must reproduce the above copyright |
12 | notice, this list of conditions and the following disclaimer in the |
13 | documentation and/or other materials provided with the distribution. |
14 | |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"|
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
18 | ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
25 | THE POSSIBILITY OF SUCH DAMAGE. |
26 +----------------------------------------------------------------------------+
27 */
28
29 #include "gate/environments.h"
30 #include "gate/results.h"
31 #include "gate/files.h"
32 #include "gate/synchronization.h"
33 #include "gate/utilities.h"
34
35
36 #if defined(GATE_SYS_WIN) && !defined(GATE_SYS_WIN16)
37 # define GATE_ENVIRONMENTS_WINAPI_IMPL 1
38 #elif defined(GATE_SYS_POSIX)
39 # define GATE_ENVIRONMENTS_C_ENV 1
40 # define GATE_ENVIRONMENTS_POSIX_IMPL 1
41 #elif defined(GATE_SYS_DOS)
42 # define GATE_ENVIRONMENTS_C_ENV 1
43 # define GATE_ENVIRONMENTS_DOS_IMPL 1
44 #else
45 # define GATE_ENVIRONMENTS_NO_IMPL 1
46 #endif
47
48
49 #ifndef SIZE_MAX
50 #define SIZE_MAX UINT_MAX
51 #endif
52
53 14 static gate_result_t gate_env_patch_path(gate_string_t* path)
54 {
55 static gate_string_t const token = { &gate_file_path_separator_char, 1, NULL };
56 14 gate_result_t ret = GATE_RESULT_OK;
57 do
58 {
59
1/2
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
14 if (!gate_string_ends_with(path, &token))
60 {
61 gate_strbuilder_t builder;
62 14 char const* const path_ptr = gate_string_ptr(path, 0);
63 14 gate_size_t const path_len = gate_string_length(path);
64
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 gate_size_t const alloc_len = (SIZE_MAX - path_len) > 4 ? path_len + 4 : path_len;
65 gate_string_t new_path;
66
67 14 gate_strbuilder_create(&builder, alloc_len);
68
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
14 if (0 == gate_strbuilder_append_text(&builder, path_ptr, path_len))
69 {
70 ret = GATE_RESULT_OUTOFMEMORY;
71 break;
72 }
73
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
14 if (0 == gate_strbuilder_append_text(&builder, gate_file_path_separator, 1))
74 {
75 ret = GATE_RESULT_OUTOFMEMORY;
76 break;
77 }
78
79
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
14 if (NULL == gate_strbuilder_to_string(&builder, &new_path))
80 {
81 ret = GATE_RESULT_OUTOFMEMORY;
82 break;
83 }
84 /* replace path string with new content */
85 14 gate_string_release(path);
86 14 gate_mem_copy(path, &new_path, sizeof(new_path));
87 }
88
89 } while (0);
90 14 return ret;
91 }
92
93
94 11 gate_result_t gate_env_app_executable_name(gate_string_t* executablename)
95 {
96 11 gate_result_t ret = GATE_RESULT_OK;
97 char buffer[GATE_MAX_FILEPATH_LENGTH];
98 11 gate_size_t buffer_len = sizeof(buffer);
99
100 11 ret = gate_env_app_executable_name_str(buffer, &buffer_len);
101
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 if (GATE_SUCCEEDED(ret))
102 {
103
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
11 if (NULL == gate_string_create(executablename, buffer, buffer_len))
104 {
105 ret = GATE_RESULT_OUTOFMEMORY;
106 }
107 }
108 11 return ret;
109 }
110
111 90 static gate_bool_t gate_env_get_var_map_cb(char const* varname, char const* varvalue, void* userparam)
112 {
113 90 gate_map_t* ptr_map = (gate_map_t*)userparam;
114 90 gate_string_t name = GATE_STRING_INIT_EMPTY;
115 90 gate_string_t value = GATE_STRING_INIT_EMPTY;
116
117 do
118 {
119
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 90 times.
90 if (NULL == gate_string_create(&name, varname, gate_str_length(varname)))
120 {
121 break;
122 }
123
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 90 times.
90 if (NULL == gate_string_create(&value, varvalue, gate_str_length(varvalue)))
124 {
125 break;
126 }
127 90 gate_map_add(ptr_map, &name, &value);
128 } while (0);
129
130 90 gate_string_release(&name);
131 90 gate_string_release(&value);
132 90 return true;
133 }
134
135 1 gate_result_t gate_env_get_var_map(gate_map_t* strmap)
136 {
137 1 gate_result_t ret = GATE_RESULT_FAILED;
138 gate_map_t varmap;
139
140 do
141 {
142 1 gate_mem_clear(&varmap, sizeof(varmap));
143
144
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (NULL == gate_util_stringmap_create(&varmap))
145 {
146 ret = GATE_RESULT_OUTOFMEMORY;
147 break;
148 }
149
150 1 ret = gate_env_list_vars(&gate_env_get_var_map_cb, &varmap);
151
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
152
153 1 gate_mem_copy(strmap, &varmap, sizeof(varmap));
154 1 gate_mem_clear(&varmap, sizeof(varmap));
155 1 ret = GATE_RESULT_OK;
156 } while (0);
157
158
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (GATE_FAILED(ret))
159 {
160 gate_map_destroy(&varmap);
161 }
162
163 1 return ret;
164 }
165
166
167
168 #if defined(GATE_ENVIRONMENTS_WINAPI_IMPL)
169
170 #include "gate/platform/windows/win32com.h"
171 #include "gate/platforms.h"
172 #include "gate/libraries.h"
173 #include "gate/atomics.h"
174 #include "gate/platform/windows/win32registry.h"
175
176 #define NOCOMMANDBAR
177 /*#include <shlobj.h>*/
178
179 gate_result_t gate_env_list_vars(gate_env_enum_callback_t callback, void* userparam)
180 {
181 gate_result_t ret = GATE_RESULT_OK;
182 #if defined(GATE_SYS_WINCE)
183 /*TODO*/
184 #else
185 gate_char8_t namebuffer[1024];
186 gate_char8_t valuebuffer[8192];
187 LPTCH environment_strings = GetEnvironmentStrings();
188 LPTCH envstrings = environment_strings;
189 gate_size_t length;
190 gate_size_t pos;
191 gate_size_t tmp;
192
193 while (0 != (length = gate_win32_winstr_length(envstrings)))
194 {
195 pos = gate_win32_winstr_char_pos(envstrings, length, '=', 0);
196 if (pos == GATE_STR_NPOS)
197 {
198 ret = GATE_RESULT_INVALIDDATA;
199 break;
200 }
201 if (callback != NULL)
202 {
203 tmp = gate_win32_winstr_2_utf8(&envstrings[0], pos, &namebuffer[0], sizeof(namebuffer) - 1);
204 namebuffer[tmp] = 0;
205 tmp = gate_win32_winstr_2_utf8(&envstrings[pos + 1], length - pos - 1, &valuebuffer[0], sizeof(valuebuffer) - 1);
206 valuebuffer[tmp] = 0;
207 if (!callback(namebuffer, valuebuffer, userparam))
208 {
209 break;
210 }
211 }
212 envstrings += length + 1;
213 }
214 if (environment_strings)
215 {
216 FreeEnvironmentStrings(environment_strings);
217 }
218 #endif
219 return ret;
220 }
221
222 gate_result_t gate_env_get_var_str(char const* varname, gate_size_t name_length, char* value, gate_size_t value_length, gate_size_t* value_used)
223 {
224 gate_result_t ret = GATE_RESULT_FAILED;
225 #if defined(GATE_SYS_WINCE)
226 /*TODO*/
227 ret = GATE_RESULT_NOTAVAILABLE;
228 #else
229 TCHAR namebuffer[1024];
230 TCHAR valuebuffer[6144];
231 DWORD bufferused;
232 DWORD errorcode;
233 gate_size_t used = 0;
234
235 do
236 {
237 if (0 == gate_win32_utf8_2_winstr(varname, name_length, namebuffer, sizeof(namebuffer) / sizeof(namebuffer[0])))
238 {
239 break;
240 }
241 SetLastError(0);
242 bufferused = GetEnvironmentVariable(namebuffer, valuebuffer, sizeof(valuebuffer) / sizeof(valuebuffer[0]));
243 if (bufferused == 0)
244 {
245 errorcode = gate_win32_getlasterror();
246 if (errorcode == ERROR_SUCCESS)
247 {
248 used = gate_win32_winstr_2_utf8(_T(""), bufferused, value, value_length);
249 ret = GATE_RESULT_OK;
250 }
251 else if (errorcode == ERROR_ENVVAR_NOT_FOUND)
252 {
253 ret = GATE_RESULT_NOTAVAILABLE;
254 }
255 else
256 {
257 gate_win32_print_lasterror(&ret, NULL, 0);
258 }
259 }
260 else
261 {
262 used = gate_win32_winstr_2_utf8(valuebuffer, bufferused, value, value_length);
263 if (used == 0)
264 {
265 ret = GATE_RESULT_OUTOFMEMORY;
266 }
267 else
268 {
269 ret = GATE_RESULT_OK;
270 }
271 }
272
273 } while (0);
274
275
276 if (value_used != NULL)
277 {
278 *value_used = used;
279 }
280 #endif
281 return ret;
282 }
283
284
285 gate_result_t gate_env_get_var(gate_string_t const* varname, gate_string_t* varvalue)
286 {
287 gate_result_t ret;
288 char buffer[4096 + 2048];
289 gate_size_t buffer_used;
290 ret = gate_env_get_var_str(varname->str, varname->length, &buffer[0], sizeof(buffer), &buffer_used);
291
292 if (GATE_SUCCEEDED(ret))
293 {
294 if (NULL == gate_string_create(varvalue, &buffer[0], buffer_used))
295 {
296 ret = GATE_RESULT_OUTOFMEMORY;
297 }
298 }
299 return ret;
300 }
301
302 gate_result_t gate_env_get_workpath(gate_string_t* workpath)
303 {
304 gate_result_t ret;
305 #ifdef GATE_SYS_WINCE
306 ret = gate_env_app_rootpath(workpath);
307 #else
308 TCHAR path[GATE_MAX_FILEPATH_LENGTH];
309 DWORD length;
310 do
311 {
312 length = GetCurrentDirectory(sizeof(path) / sizeof(path[0]), path);
313 if (length == 0)
314 {
315 gate_win32_print_lasterror(&ret, NULL, 0);
316 break;
317 }
318 if (NULL == gate_win32_winstr_2_utf8_string(path, length, workpath))
319 {
320 ret = GATE_RESULT_OUTOFMEMORY;
321 break;
322 }
323 ret = GATE_RESULT_OK;
324 } while (0);
325 #endif
326 return ret;
327 }
328 gate_result_t gate_env_set_workpath(gate_string_t const* workpath)
329 {
330 gate_result_t ret;
331 #if defined(GATE_SYS_WINCE)
332 ret = GATE_RESULT_NOTSUPPORTED;
333 #else
334 TCHAR path[GATE_MAX_FILEPATH_LENGTH];
335 do
336 {
337 if (gate_string_is_empty(workpath))
338 {
339 ret = GATE_RESULT_INVALIDARG;
340 break;
341 }
342 gate_win32_utf8_2_winstr(workpath->str, workpath->length, path, sizeof(path) / sizeof(path[0]));
343 if (SetCurrentDirectory(path))
344 {
345 ret = GATE_RESULT_OK;
346 }
347 else
348 {
349 gate_win32_print_lasterror(&ret, NULL, 0);
350 }
351 } while (0);
352 #endif
353 return ret;
354 }
355
356
357 #include "gate/struct_pack_begin.h"
358 typedef struct _GATE_SHITEMID
359 {
360 USHORT cb;
361 BYTE abID[1];
362 } GATE_SHITEMID;
363
364 typedef struct _GATE_ITEMIDLIST
365 {
366 GATE_SHITEMID mkid;
367 } GATE_ITEMIDLIST;
368
369 typedef GATE_ITEMIDLIST /*__unaligned*/* LPGATEITEMIDLIST;
370 #include "gate/struct_pack_end.h"
371
372 #if defined(GATE_WIN32_UNICODE)
373 # define SHGetFolderPath_Name "SHGetFolderPathW"
374 # define SHGetSpecialFolderPath_Name "SHGetSpecialFolderPathW"
375 # define SHGetPathFromIDList_Name "SHGetPathFromIDListW"
376 #else
377 # define SHGetFolderPath_Name "SHGetFolderPathA"
378 # define SHGetSpecialFolderPath_Name "SHGetSpecialFolderPathA"
379 # define SHGetPathFromIDList_Name "SHGetPathFromIDListA"
380 #endif
381
382 typedef HRESULT(WINAPI* SHGetFolderPath_t) (HWND hwndOwner, int nFolder, HANDLE hToken, DWORD dwFlags, LPTSTR pszPath);
383 typedef HRESULT(WINAPI* SHGetSpecialFolderLocation_t) (HWND hwndOwner, int csidl, LPGATEITEMIDLIST* ppidl);
384 typedef BOOL(WINAPI* SHGetSpecialFolderPath_t) (HWND hwndOwner, LPTSTR lpszPath, int nFolder, BOOL fCreate);
385 typedef BOOL(WINAPI* SHGetPathFromIDList_t) (LPGATEITEMIDLIST pidl, LPTSTR pszPath);
386
387
388 static SHGetFolderPath_t sh_get_folder_path = NULL;
389 static SHGetSpecialFolderPath_t sh_get_special_folder_path = NULL;
390 static SHGetSpecialFolderLocation_t sh_get_special_folder_location = NULL;
391 static SHGetPathFromIDList_t sh_get_path_from_idlist = NULL;
392 static gate_atomic_flag_t folder_path_function_loaded = GATE_ATOMIC_FLAG_INIT;
393
394
395 static gate_bool_t load_shell_specialfolderpath()
396 {
397 HMODULE hmodshell = gate_win32_get_shell_module();
398
399 if (gate_atomic_flag_set(&folder_path_function_loaded) == false)
400 {
401 gate_win32_get_proc_address(hmodshell, SHGetFolderPath_Name, &sh_get_folder_path);
402 gate_win32_get_proc_address(hmodshell, SHGetSpecialFolderPath_Name, &sh_get_special_folder_path);
403 gate_win32_get_proc_address(hmodshell, "SHGetSpecialFolderLocation", &sh_get_special_folder_location);
404 gate_win32_get_proc_address(hmodshell, SHGetPathFromIDList_Name, &sh_get_path_from_idlist);
405 }
406 return (sh_get_special_folder_path != NULL) || (sh_get_special_folder_location != NULL);
407 }
408
409
410 static gate_result_t tstr_to_char_buffer(TCHAR* src, char* target, gate_size_t* targetlen)
411 {
412 gate_size_t length;
413 gate_size_t targetused;
414
415 length = gate_win32_winstr_length(src);
416 if (src[length - 1] != '\\')
417 {
418 src[length] = '\\';
419 ++length;
420 }
421 targetused = gate_win32_winstr_2_utf8(src, length, target, *targetlen);
422 if (targetused == 0)
423 {
424 return GATE_RESULT_OUTOFMEMORY;
425 }
426 *targetlen = targetused;
427 return GATE_RESULT_OK;
428 }
429
430 static gate_result_t gate_win32_special_folder_str(int nFolder, char* target, gate_size_t* targetlen)
431 {
432 gate_result_t ret = GATE_RESULT_FAILED;
433 TCHAR pathbuffer[GATE_MAX_FILEPATH_LENGTH];
434 LPGATEITEMIDLIST ptrl_itemidlist = NULL;
435
436 if (!load_shell_specialfolderpath())
437 {
438 ret = GATE_RESULT_NOTSUPPORTED;
439 }
440 else
441 {
442 gate_mem_clear(pathbuffer, sizeof(pathbuffer));
443 do
444 {
445 if (sh_get_folder_path && (S_OK == sh_get_folder_path(NULL, nFolder, NULL, 0, pathbuffer)))
446 {
447 ret = tstr_to_char_buffer(pathbuffer, target, targetlen);
448 break;
449 }
450
451 if (sh_get_special_folder_path && sh_get_special_folder_path(NULL, pathbuffer, nFolder, TRUE))
452 {
453 ret = tstr_to_char_buffer(pathbuffer, target, targetlen);
454 break;
455 }
456 if (sh_get_special_folder_location && sh_get_path_from_idlist && SUCCEEDED(sh_get_special_folder_location(NULL, nFolder, &ptrl_itemidlist)))
457 {
458 if (!sh_get_path_from_idlist(ptrl_itemidlist, pathbuffer))
459 {
460 ret = GATE_RESULT_FAILED;
461 }
462 else
463 {
464 ret = tstr_to_char_buffer(pathbuffer, target, targetlen);
465 }
466 gate_win32_com_dealloc(ptrl_itemidlist);
467 break;
468 }
469 } while (0);
470 }
471 return ret;
472 }
473
474
475 static gate_result_t gate_win32_special_folder(int nFolder, gate_string_t* path)
476 {
477 char buffer[GATE_MAX_FILEPATH_LENGTH * 2];
478 gate_size_t bufferlen = sizeof(buffer);
479 gate_result_t ret = gate_win32_special_folder_str(nFolder, buffer, &bufferlen);
480 if (GATE_SUCCEEDED(ret))
481 {
482 if (NULL == gate_string_create(path, buffer, bufferlen))
483 {
484 ret = GATE_RESULT_OUTOFMEMORY;
485 }
486 }
487 return ret;
488 }
489
490
491 gate_result_t gate_env_temp_rootpath(gate_string_t* temppath)
492 {
493 gate_result_t ret;
494 TCHAR path[GATE_MAX_FILEPATH_LENGTH];
495 DWORD length = GetTempPath(sizeof(path) / sizeof(path[0]) - 1, path);
496 if (length == 0)
497 {
498 ret = GATE_RESULT_FAILED;
499 }
500 else
501 {
502 if (path[length - 1] != '\\')
503 {
504 path[length] = '\\';
505 ++length;
506 }
507 if (NULL == gate_win32_winstr_2_utf8_string(path, length, temppath))
508 {
509 ret = GATE_RESULT_OUTOFMEMORY;
510 }
511 else
512 {
513 ret = GATE_RESULT_OK;
514 }
515 }
516 return ret;
517 }
518
519 #ifndef CSIDL_PROFILE
520 #define CSIDL_PROFILE 0x0028
521 #endif
522
523 #ifndef CSIDL_DESKTOPDIRECTORY
524 #define CSIDL_DESKTOPDIRECTORY 0x0010
525 #endif
526
527 #ifndef CSIDL_APPDATA
528 #define CSIDL_APPDATA 0x001a
529 #endif
530
531 #ifndef CSIDL_COMMON_DOCUMENTS
532 #define CSIDL_COMMON_DOCUMENTS 0x002e
533 #endif
534
535 #ifndef CSIDL_MYDOCUMENTS
536 #define CSIDL_MYDOCUMENTS 0x000c
537 #endif
538
539 #ifndef CSIDL_COMMON_APPDATA
540 #define CSIDL_COMMON_APPDATA 0x023
541 #endif
542
543 #ifndef CSIDL_APPDATA
544 #define CSIDL_APPDATA 0x001a
545 #endif
546
547 #ifndef CSIDL_LOCAL_APPDATA
548 #define CSIDL_LOCAL_APPDATA 0x001c
549 #endif
550
551 #ifndef CSIDL_MYPICTURES
552 #define CSIDL_MYPICTURES 0x027
553 #endif
554
555 #ifndef CSIDL_MYMUSIC
556 #define CSIDL_MYMUSIC 0x00d
557 #endif
558
559 #ifndef CSIDL_MYVIDEO
560 #define CSIDL_MYVIDEO 0x00e
561 #endif
562
563 #ifndef CSIDL_PERSONAL
564 #define CSIDL_PERSONAL 0x0005
565 #endif
566
567 #ifndef CSIDL_DESKTOPDIRECTORY
568 #define CSIDL_DESKTOPDIRECTORY 0x0010
569 #endif
570
571
572 gate_result_t gate_env_home_rootpath(gate_string_t* homepath)
573 {
574 gate_result_t ret = gate_win32_special_folder(CSIDL_PROFILE, homepath);
575 static gate_string_t userprofile_var = { "USERPROFILE", 11, NULL };
576 if (GATE_FAILED(ret))
577 {
578 ret = gate_env_get_var(&userprofile_var, homepath);
579 }
580
581 /* NOTICE: Win9x has no profile/user paths, try other options
582 It depends on IE+shell version, which folder is available */
583 if (GATE_FAILED(ret))
584 {
585 /* user documents folder */
586 ret = gate_win32_special_folder(CSIDL_MYDOCUMENTS, homepath);
587 }
588 if (GATE_FAILED(ret))
589 {
590 /* all-users documents folder */
591 ret = gate_win32_special_folder(CSIDL_COMMON_DOCUMENTS, homepath);
592 }
593 if (GATE_FAILED(ret))
594 {
595 /* app-data folder */
596 ret = gate_win32_special_folder(CSIDL_LOCAL_APPDATA, homepath);
597 }
598 if (GATE_FAILED(ret))
599 {
600 /* desktop */
601 ret = gate_win32_special_folder(CSIDL_DESKTOPDIRECTORY, homepath);
602 }
603 if (GATE_FAILED(ret))
604 {
605 /* app-data folder */
606 ret = gate_win32_special_folder(CSIDL_APPDATA, homepath);
607 }
608
609 if (GATE_SUCCEEDED(ret))
610 {
611 ret = gate_env_patch_path(homepath);
612 }
613 return ret;
614 }
615
616 gate_result_t gate_env_app_executable_str(char* buffer, gate_size_t* buffer_len)
617 {
618 gate_result_t ret = GATE_RESULT_OK;
619 TCHAR path[GATE_MAX_FILEPATH_LENGTH];
620 DWORD length = GetModuleFileName(NULL, path, sizeof(path) / sizeof(path[0]) - 1);
621 gate_size_t buffer_used;
622 if (length == 0)
623 {
624 ret = GATE_RESULT_FAILED;
625 }
626 else
627 {
628 buffer_used = gate_win32_winstr_2_utf8(path, length, buffer, *buffer_len);
629 if (buffer_used)
630 {
631 *buffer_len = buffer_used;
632 }
633 else
634 {
635 ret = GATE_RESULT_OUTOFMEMORY;
636 }
637 }
638 return ret;
639 }
640
641 gate_result_t gate_env_app_executable(gate_string_t* executablepath)
642 {
643 gate_result_t ret = GATE_RESULT_OK;
644 TCHAR path[GATE_MAX_FILEPATH_LENGTH];
645 DWORD length = GetModuleFileName(NULL, path, sizeof(path) / sizeof(path[0]) - 1);
646 if (length == 0)
647 {
648 ret = GATE_RESULT_FAILED;
649 }
650 else
651 {
652 if (NULL == gate_win32_winstr_2_utf8_string(path, length, executablepath))
653 {
654 ret = GATE_RESULT_OUTOFMEMORY;
655 }
656 }
657 return ret;
658 }
659
660 gate_result_t gate_env_app_executable_name_str(char* buffer, gate_size_t* buffer_len)
661 {
662 gate_result_t ret = GATE_RESULT_OK;
663 gate_size_t pos;
664 TCHAR path[GATE_MAX_FILEPATH_LENGTH];
665 DWORD length = GetModuleFileName(NULL, path, sizeof(path) / sizeof(path[0]) - 1);
666 gate_size_t buffer_used = 0;
667
668 if (length == 0)
669 {
670 ret = GATE_RESULT_FAILED;
671 }
672 else
673 {
674 pos = gate_win32_winstr_char_pos_last(path, length, '\\');
675 if (pos == GATE_STR_NPOS)
676 {
677 ret = GATE_RESULT_INVALIDDATA;
678 }
679 else
680 {
681 buffer_used = gate_win32_winstr_2_utf8(&path[pos + 1], length - pos - 1, buffer, *buffer_len);
682 *buffer_len = buffer_used;
683 }
684 }
685 return ret;
686 }
687
688 gate_result_t gate_env_app_configpath(gate_string_t const* appname, gate_bool_t global_config, gate_string_t* appdatapath)
689 {
690 char buffer[GATE_MAX_FILEPATH_LENGTH * 2];
691 gate_strbuilder_t builder;
692 gate_size_t appnamelen;
693 gate_size_t bufferlen = sizeof(buffer);
694 gate_result_t ret = gate_win32_special_folder_str(global_config ? CSIDL_COMMON_APPDATA : CSIDL_APPDATA, buffer, &bufferlen);
695 if (GATE_SUCCEEDED(ret))
696 {
697 appnamelen = gate_string_length(appname);
698 if (appnamelen == 0)
699 {
700 if (NULL == gate_string_create(appdatapath, buffer, bufferlen))
701 {
702 ret = GATE_RESULT_OUTOFMEMORY;
703 }
704 }
705 else
706 {
707 gate_strbuilder_create(&builder, bufferlen + appnamelen + 2);
708 ret = GATE_RESULT_OUTOFMEMORY;
709 do
710 {
711 if (0 == gate_strbuilder_append_text(&builder, buffer, bufferlen)) break;
712 if (0 == gate_strbuilder_append_text(&builder, appname->str, appname->length)) break;
713 if (0 == gate_strbuilder_append_text(&builder, "\\", 1)) break;
714 if (NULL == gate_strbuilder_to_string(&builder, appdatapath)) break;
715
716 ret = GATE_RESULT_OK;
717
718 /* the directory may not exist, try to create it as an optional step here */
719 if (0 != gate_win32_string_2_winstr(appdatapath, (LPTSTR)&buffer[0], sizeof(buffer) / 2))
720 {
721 CreateDirectory((LPCTSTR)&buffer[0], NULL);
722 }
723 } while (0);
724 gate_strbuilder_release(&builder);
725 }
726 }
727 return ret;
728 }
729
730 gate_result_t gate_env_app_rootpath(gate_string_t* apppath)
731 {
732 gate_result_t ret = GATE_RESULT_OK;
733 gate_size_t pos;
734 TCHAR path[GATE_MAX_FILEPATH_LENGTH];
735 DWORD length = GetModuleFileName(NULL, path, sizeof(path) / sizeof(path[0]) - 1);
736 if (length == 0)
737 {
738 ret = GATE_RESULT_FAILED;
739 }
740 else
741 {
742 pos = gate_win32_winstr_char_pos_last(path, length, '\\');
743 if (pos == GATE_STR_NPOS)
744 {
745 ret = GATE_RESULT_INVALIDDATA;
746 }
747 else
748 {
749 if (NULL == gate_win32_winstr_2_utf8_string(path, pos + 1, apppath))
750 {
751 ret = GATE_RESULT_OUTOFMEMORY;
752 }
753 }
754 }
755 return ret;
756 }
757
758 gate_result_t gate_env_data_path(gate_uint32_t dataid, gate_string_t* appdatapath)
759 {
760 gate_result_t ret;
761 int csidl;
762 switch (dataid)
763 {
764 case GATE_ENV_DOCUMENTS: csidl = CSIDL_PERSONAL; break;
765 case GATE_ENV_PICTURES: csidl = CSIDL_MYPICTURES; break;
766 case GATE_ENV_MUSIC: csidl = CSIDL_MYMUSIC; break;
767 case GATE_ENV_VIDEOS: csidl = CSIDL_MYVIDEO; break;
768 case GATE_ENV_DESKTOP: csidl = CSIDL_DESKTOPDIRECTORY; break;
769 case GATE_ENV_APPDATA: csidl = CSIDL_LOCAL_APPDATA; break;
770 default: return GATE_RESULT_INVALIDARG;
771 }
772
773 ret = gate_win32_special_folder(csidl, appdatapath);
774
775 return ret;
776 }
777
778 gate_result_t gate_env_host_name(gate_string_t* hostname)
779 {
780 gate_result_t ret = GATE_RESULT_OK;
781 #ifdef GATE_SYS_WINCE
782 char name[GATE_MAX_FILENAME_LENGTH];
783 gate_size_t name_length = 0;
784 ret = gate_win32_registry_read_str(GATE_WIN32_REGISTRY_LOCALMACHINE, _T("Ident"), _T("Name"), name, sizeof(name), &name_length);
785 if (GATE_SUCCEEDED(ret))
786 {
787 if (NULL == gate_string_create(hostname, name, name_length))
788 {
789 ret = GATE_RESULT_OUTOFMEMORY;
790 }
791 else
792 {
793 ret = GATE_RESULT_OK;
794 }
795 }
796 #else
797 static gate_string_t const computername_var = { "COMPUTERNAME", 12, NULL };
798 TCHAR name[GATE_MAX_FILENAME_LENGTH];
799 DWORD length = sizeof(name) / sizeof(name[0]);
800
801 if (GetComputerName(name, &length))
802 {
803 if (NULL == gate_win32_winstr_2_utf8_string(name, length, hostname))
804 {
805 ret = GATE_RESULT_OUTOFMEMORY;
806 }
807 }
808 else
809 {
810 ret = gate_env_get_var(&computername_var, hostname);
811 }
812 #endif
813 return ret;
814 }
815 gate_result_t gate_env_user_name(gate_string_t* username)
816 {
817 gate_result_t ret = GATE_RESULT_OK;
818 #ifdef GATE_SYS_WINCE
819 gate_string_create_empty(username);
820 #else
821 static gate_string_t const username_var = GATE_STRING_INIT_STATIC("USERNAME");
822 TCHAR name[GATE_MAX_FILENAME_LENGTH];
823 DWORD length = sizeof(name) / sizeof(name[0]);
824
825 do
826 {
827 if (gate_platform.AdvGetUserName)
828 {
829 if (gate_platform.AdvGetUserName(name, &length))
830 {
831 if (NULL == gate_win32_winstr_2_utf8_string(name, length, username))
832 {
833 ret = GATE_RESULT_OUTOFMEMORY;
834 }
835 else
836 {
837 ret = GATE_RESULT_OK;
838 }
839 break;
840 }
841 }
842
843 ret = gate_env_get_var(&username_var, username);
844
845 } while (0);
846
847 #endif
848 return ret;
849 }
850
851 gate_result_t gate_env_shell_path(gate_string_t* shellpath)
852 {
853 static gate_string_t const comspec_var = GATE_STRING_INIT_STATIC("COMSPEC");
854 gate_result_t result = gate_env_get_var(&comspec_var, shellpath);
855 if (GATE_FAILED(result))
856 {
857 DWORD dwMajor = 0, dwMinor = 0, dwBuild = 0;
858 BOOL isNT = FALSE;
859 gate_win32_get_version(&dwMajor, &dwMinor, &dwBuild, &isNT);
860 if (isNT)
861 {
862 gate_string_create_static(shellpath, "cmd.exe");
863 }
864 else
865 {
866 gate_string_create_static(shellpath, "command.com");
867 }
868 result = GATE_RESULT_OK;
869 }
870 return result;
871 }
872
873 #endif /* GATE_ENVIRONMENTS_WINAPI_IMPL */
874
875
876 #if defined(GATE_ENVIRONMENTS_C_ENV)
877 #include "gate/platforms.h"
878 #include "gate/files.h"
879
880 #include <stdio.h>
881 #include <stdlib.h>
882 #include <errno.h>
883
884 #if defined(GATE_SYS_POSIX)
885 # if defined(GATE_SYS_ANDROID)
886 # elif defined(GATE_SYS_LINUX)
887 # include <sys/auxv.h>
888 # endif
889
890 # include <pwd.h>
891 # include <grp.h>
892 # include <sys/types.h>
893 # include <sys/stat.h>
894
895 extern char** environ;
896
897 #endif
898
899 #if defined(GATE_SYS_DOS)
900 # include <direct.h>
901 #endif
902
903 2 gate_result_t gate_env_list_vars(gate_env_enum_callback_t callback, void* userparam)
904 {
905 gate_result_t ret;
906 2 char const* const* env = (char const* const*)environ;
907
908
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (env == NULL)
909 {
910 ret = GATE_RESULT_NOTAVAILABLE;
911 }
912 else
913 {
914
2/2
✓ Branch 0 taken 180 times.
✓ Branch 1 taken 2 times.
182 while (*env != NULL)
915 {
916 180 gate_size_t length = gate_str_length(*env);
917 180 gate_size_t pos = gate_str_char_pos(*env, length, '=', 0);
918
2/4
✓ Branch 0 taken 180 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 180 times.
✗ Branch 3 not taken.
180 if ((pos != GATE_STR_NPOS) && (callback != NULL))
919 {
920 char varname[2048];
921 char varvalue[8192];
922 180 gate_str_print_text(varname, sizeof(varname), *env, pos);
923 180 gate_str_print_text(varvalue, sizeof(varvalue), &((*env)[pos + 1]), length - pos - 1);
924
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 180 times.
180 if (!callback(varname, varvalue, userparam))
925 {
926 break;
927 }
928 }
929 180 ++env;
930 }
931 2 ret = GATE_RESULT_OK;
932 }
933 2 return ret;
934 }
935 198 gate_result_t gate_env_get_var(gate_string_t const* varname, gate_string_t* varvalue)
936 {
937 gate_result_t ret;
938 char namebuffer[2048];
939 char* ptrenv;
940
941 198 gate_string_to_buffer(varname, namebuffer, sizeof(namebuffer));
942 198 ptrenv = getenv(namebuffer);
943
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 194 times.
198 if (ptrenv == NULL)
944 {
945 4 ret = GATE_RESULT_NOTAVAILABLE;
946 }
947 else
948 {
949
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 194 times.
194 if (NULL == gate_string_create_static_len(varvalue, ptrenv, gate_str_length(ptrenv)))
950 {
951 ret = GATE_RESULT_OUTOFMEMORY;
952 }
953 else
954 {
955 194 ret = GATE_RESULT_OK;
956 }
957 }
958 198 return ret;
959 }
960 gate_result_t gate_env_get_var_str(char const* varname, gate_size_t name_length, char* value, gate_size_t value_length, gate_size_t* value_used)
961 {
962 gate_result_t ret;
963 char namebuffer[2048];
964 char* ptrenv;
965 gate_size_t used;
966 gate_str_print_text(namebuffer, sizeof(namebuffer), varname, name_length);
967 ptrenv = getenv(namebuffer);
968 if (ptrenv == NULL)
969 {
970 ret = GATE_RESULT_NOTAVAILABLE;
971 }
972 else
973 {
974 used = gate_str_print_text(value, value_length, ptrenv, gate_str_length(ptrenv));
975 if (value_used != NULL)
976 {
977 *value_used = used;
978 }
979 ret = GATE_RESULT_OK;
980 }
981 return ret;
982 }
983
984 5 gate_result_t gate_env_get_workpath(gate_string_t* workpath)
985 {
986 gate_result_t ret;
987 char path[GATE_MAX_FILEPATH_LENGTH];
988 5 gate_size_t length = sizeof(path) - 1;
989 5 char* ptr = getcwd(path, length);
990
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (ptr == NULL)
991 {
992 ret = GATE_RESULT_FAILED;
993 }
994 else
995 {
996 5 length = gate_str_length(ptr);
997
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (path[length - 1] != gate_file_path_separator_char)
998 {
999 5 path[length] = gate_file_path_separator_char;
1000 5 ++length;
1001 }
1002
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
5 if (NULL == gate_string_create(workpath, path, length))
1003 {
1004 ret = GATE_RESULT_OUTOFMEMORY;
1005 }
1006 else
1007 {
1008 5 ret = GATE_RESULT_OK;
1009 }
1010 }
1011 5 return ret;
1012 }
1013
1014 1 gate_result_t gate_env_set_workpath(gate_string_t const* workpath)
1015 {
1016 gate_result_t ret;
1017 char path[GATE_MAX_FILEPATH_LENGTH];
1018 1 gate_string_to_buffer(workpath, path, sizeof(path));
1019
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (-1 == chdir(path))
1020 {
1021 ret = gate_platform_print_last_error(NULL, 0);
1022 }
1023 else
1024 {
1025 1 ret = GATE_RESULT_OK;
1026 }
1027 1 return ret;
1028 }
1029
1030 14 static gate_result_t gate_env_select_var(gate_string_t const* env_vars, gate_size_t env_vars_count, gate_string_t* output)
1031 {
1032 gate_size_t cnt;
1033 14 gate_result_t ret = GATE_RESULT_NOTAVAILABLE;
1034
1035
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 for (cnt = 0; cnt != env_vars_count; ++cnt)
1036 {
1037 14 ret = gate_env_get_var(&env_vars[cnt], output);
1038
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 if (GATE_SUCCEEDED(ret))
1039 {
1040 14 return ret;
1041 }
1042 }
1043 return ret;
1044 }
1045
1046 14 gate_result_t gate_env_read_path_entry(gate_string_t const* ptr_env_names, gate_size_t env_names_count, gate_string_t* out_path)
1047 {
1048 gate_result_t ret;
1049 14 ret = gate_env_select_var(ptr_env_names, env_names_count, out_path);
1050
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 if (GATE_SUCCEEDED(ret))
1051 {
1052 14 ret = gate_env_patch_path(out_path);
1053 }
1054 14 return ret;
1055
1056 }
1057
1058 14 gate_result_t gate_env_home_rootpath(gate_string_t* homepath)
1059 {
1060 gate_result_t ret;
1061 static gate_string_t const homedir_vars[] =
1062 {
1063 GATE_STRING_INIT_STATIC("HOME"),
1064 GATE_STRING_INIT_STATIC("USERPROFILE")
1065 };
1066 14 ret = gate_env_read_path_entry(homedir_vars, sizeof(homedir_vars) / sizeof(homedir_vars[0]), homepath);
1067
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (GATE_FAILED(ret))
1068 {
1069 ret = gate_env_temp_rootpath(homepath);
1070 }
1071 14 return ret;
1072 }
1073
1074
1075 #endif /* GATE_ENVIRONMENTS_C_ENV */
1076
1077
1078
1079 #if defined(GATE_ENVIRONMENTS_POSIX_IMPL)
1080
1081 #if defined(GATE_SYS_BSD)
1082 # include <sys/sysctl.h>
1083 # include <sys/stat.h>
1084 # include <unistd.h>
1085
1086 #if defined(KERN_PROC_PATHNAME)
1087
1088 static gate_size_t bsd_get_first_process_arg(char* buffer, gate_size_t buffer_capacity)
1089 {
1090 int mib[4];
1091 char buf[PATH_MAX];
1092 size_t cb = sizeof(buf);
1093
1094 mib[0] = CTL_KERN;
1095 mib[1] = KERN_PROC;
1096 mib[2] = KERN_PROC_PATHNAME;
1097 mib[3] = -1;
1098
1099 gate_mem_clear(buf, sizeof(buf));
1100 if (0 == sysctl(mib, 4, buf, &cb, NULL, 0))
1101 {
1102 return gate_str_print_text(buffer, buffer_capacity, &buf[0], gate_str_length(&buf[0]));
1103 }
1104 return 0;
1105 }
1106
1107 #else /* defined(KERN_PROC_PATHNAME) */
1108
1109 static gate_size_t bsd_get_first_process_arg(char* buffer, gate_size_t buffer_capacity)
1110 {
1111 int mib[4];
1112 char** argv;
1113 size_t len;
1114
1115 mib[0] = CTL_KERN;
1116 mib[1] = KERN_PROC_ARGS;
1117 mib[2] = getpid();
1118 mib[3] = KERN_PROC_ARGV;
1119
1120 if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), NULL, &len, NULL, 0) < 0)
1121 {
1122 return 0;
1123 }
1124 argv = (char**)gate_mem_alloc(len);
1125 if (argv == NULL)
1126 {
1127 return 0;
1128 }
1129
1130 if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), argv, &len, NULL, 0) < 0)
1131 {
1132 len = 0;
1133 }
1134 else
1135 {
1136 len = gate_str_print_text(buffer, buffer_capacity, argv[0], gate_str_length(argv[0]));
1137 }
1138 gate_mem_dealloc(argv);
1139 return len;
1140 }
1141 #endif /* defined(KERN_PROC_PATHNAME) */
1142
1143 static gate_size_t bsd_get_valid_path(char const* base_path, gate_size_t base_path_len,
1144 char const* rel_path, gate_size_t rel_path_len,
1145 char* target_path, gate_size_t target_path_capacity)
1146 {
1147 gate_strbuilder_t builder;
1148 struct stat filestat;
1149 gate_strbuilder_create_static(&builder, target_path, target_path_capacity, 0);
1150 gate_strbuilder_append_text(&builder, base_path, base_path_len);
1151 if (base_path[base_path_len - 1] != '/')
1152 {
1153 gate_strbuilder_append_text(&builder, "/", 1);
1154 }
1155 gate_strbuilder_append_text(&builder, rel_path, rel_path_len);
1156
1157 if (0 == stat(gate_strbuilder_ptr(&builder, 0), &filestat))
1158 {
1159 if (filestat.st_mode & S_IXUSR)
1160 {
1161 return gate_str_print_text(target_path, target_path_capacity, gate_strbuilder_ptr(&builder, 0), gate_strbuilder_length(&builder));
1162 }
1163 }
1164 return 0;
1165 }
1166
1167 gate_size_t bsd_get_process_executable(char* buffer, gate_size_t buffer_capacity)
1168 {
1169 char full_path[PATH_MAX];
1170 gate_size_t full_path_used;
1171 gate_size_t buffer_used;
1172 char const* path_var;
1173 gate_size_t path_len;
1174 gate_size_t start, pos;
1175
1176 buffer_used = bsd_get_first_process_arg(buffer, buffer_capacity);
1177 if (buffer_used == 0)
1178 {
1179 return 0;
1180 }
1181
1182 if ((buffer[0] == '/') || (buffer[0] == '.'))
1183 {
1184 if (NULL == realpath(buffer, full_path))
1185 {
1186 return 0;
1187 }
1188 full_path_used = gate_str_length(full_path);
1189 return gate_str_print_text(buffer, buffer_capacity, full_path, full_path_used);
1190 }
1191
1192 path_var = getenv("PATH");
1193 if (path_var == NULL)
1194 {
1195 return 0;
1196 }
1197 path_len = gate_str_length(path_var);
1198 start = 0;
1199 while (start < path_len)
1200 {
1201 /* abc:def:ghi*/
1202 pos = gate_str_char_pos(path_var, path_len, ':', start);
1203 if (pos == GATE_STR_NPOS)
1204 {
1205 pos = path_len;
1206 }
1207
1208 full_path_used = bsd_get_valid_path(&path_var[start], pos - start, buffer, buffer_used, full_path, sizeof(full_path));
1209 if (full_path_used != 0)
1210 {
1211 return gate_str_print_text(buffer, buffer_capacity, full_path, full_path_used);
1212 }
1213 start = pos + 1;
1214 }
1215 return 0;
1216 }
1217
1218 #endif
1219
1220 #if defined(GATE_SYS_DARWIN)
1221
1222 #include "gate/platform/darwin/darwin_gate.h"
1223
1224 #endif
1225
1226
1227 2 gate_result_t gate_env_temp_rootpath(gate_string_t* temppath)
1228 {
1229 gate_result_t ret;
1230 static gate_string_t const tempdir_var = GATE_STRING_INIT_STATIC("TMPDIR");
1231 static gate_string_t const def_tempdir = GATE_STRING_INIT_STATIC("/tmp/");
1232 2 ret = gate_env_get_var(&tempdir_var, temppath);
1233
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (GATE_FAILED(ret))
1234 {
1235 2 gate_string_duplicate(temppath, &def_tempdir);
1236 2 ret = GATE_RESULT_OK;
1237 }
1238 else
1239 {
1240 ret = gate_env_patch_path(temppath);
1241 }
1242 2 return ret;
1243 }
1244 30 gate_result_t gate_env_app_executable_str(char* destbuffer, gate_size_t* destbuffer_length)
1245 {
1246 char buffer[GATE_MAX_FILEPATH_LENGTH];
1247 30 char const* ptr_path = NULL;
1248 30 gate_size_t destbuffer_used = 0;
1249
1250 do
1251 {
1252 ssize_t len_used;
1253 30 gate_mem_clear(&buffer[0], sizeof(buffer));
1254
1255 #if defined(GATE_SYS_BSD)
1256 destbuffer_used = bsd_get_process_executable(buffer, sizeof(buffer));
1257 if (destbuffer_used != 0)
1258 {
1259 ptr_path = &buffer[0];
1260 break;
1261 }
1262 #endif /* GATE_SYS_BSD */
1263
1264 #if defined(GATE_SYS_DARWIN)
1265 if (GATE_SUCCEEDED(gate_darwin_get_pid_path(gate_darwin_get_pid(), buffer, sizeof(buffer), &destbuffer_used)))
1266 {
1267 ptr_path = &buffer[0];
1268 break;
1269 }
1270 #endif /* GATE_SYS_DARWIN */
1271
1272 /* try procfs fall backs */
1273 30 len_used = readlink("/proc/self/exe", buffer, sizeof(buffer));
1274
1/2
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
30 if (len_used > 0)
1275 {
1276
1/2
✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
30 if (gate_posix_path_exists(&buffer[0]))
1277 {
1278 30 ptr_path = &buffer[0];
1279 30 break;
1280 }
1281 }
1282
1283 len_used = readlink("/proc/curproc/file", buffer, sizeof(buffer));
1284 if (len_used > 0)
1285 {
1286 if (gate_posix_path_exists(&buffer[0]))
1287 {
1288 ptr_path = &buffer[0];
1289 break;
1290 }
1291 }
1292
1293 len_used = readlink("/proc/self/path/a.out", buffer, sizeof(buffer));
1294 if (len_used > 0)
1295 {
1296 if (gate_posix_path_exists(&buffer[0]))
1297 {
1298 ptr_path = &buffer[0];
1299 break;
1300 }
1301 }
1302
1303 #if defined(GATE_SYS_ANDROID)
1304 /* fall-back to procfs required! */
1305 #elif defined(GATE_SYS_LINUX)
1306 ptr_path = (char const*)getauxval(AT_EXECFN);
1307 if (gate_posix_path_exists(ptr_path))
1308 {
1309 break;
1310 }
1311 #endif
1312 /* unfortunately no valid path was found */
1313 ptr_path = NULL;
1314 } while (0);
1315
1316
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (ptr_path == NULL)
1317 {
1318 return GATE_RESULT_FAILED;
1319 }
1320 else
1321 {
1322 30 destbuffer_used = gate_str_print_text(destbuffer, *destbuffer_length, ptr_path, gate_str_length(ptr_path));
1323
1/2
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
30 if (destbuffer_used > 0)
1324 {
1325 30 *destbuffer_length = destbuffer_used;
1326 30 return GATE_RESULT_OK;
1327 }
1328 else
1329 {
1330 return GATE_RESULT_OUTOFMEMORY;
1331 }
1332 }
1333 }
1334
1335 2 gate_result_t gate_env_app_executable(gate_string_t* executablepath)
1336 {
1337 2 char buffer[GATE_MAX_FILEPATH_LENGTH] = GATE_INIT_EMPTY;
1338 2 gate_size_t buffer_len = sizeof(buffer);
1339 2 gate_result_t ret = gate_env_app_executable_str(buffer, &buffer_len);
1340
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (GATE_SUCCEEDED(ret))
1341 {
1342
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (NULL == gate_string_create(executablepath, buffer, buffer_len))
1343 {
1344 ret = GATE_RESULT_OUTOFMEMORY;
1345 }
1346 }
1347 2 return ret;
1348 }
1349
1350 21 gate_result_t gate_env_app_executable_name_str(char* name_buffer, gate_size_t* name_buffer_len)
1351 {
1352 21 char buffer[GATE_MAX_FILEPATH_LENGTH] = GATE_INIT_EMPTY;
1353 21 gate_size_t buffer_len = sizeof(buffer);
1354 21 gate_result_t ret = gate_env_app_executable_str(buffer, &buffer_len);
1355 gate_size_t pos;
1356 gate_size_t name_buffer_used;
1357
1358
1/2
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
21 if (GATE_SUCCEEDED(ret))
1359 {
1360 21 pos = gate_str_find_last_of(buffer, buffer_len, "/", 1);
1361
1/2
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
21 if (pos != GATE_STR_NPOS)
1362 {
1363 21 name_buffer_used = gate_str_print_text(name_buffer, *name_buffer_len, &buffer[pos + 1], buffer_len - pos - 1);
1364 }
1365 else
1366 {
1367 name_buffer_used = gate_str_print_text(name_buffer, *name_buffer_len, buffer, buffer_len);
1368 }
1369 21 *name_buffer_len = name_buffer_used;
1370 }
1371 21 return ret;
1372 }
1373
1374
1375 1 gate_result_t gate_env_app_rootpath(gate_string_t* apppath)
1376 {
1377 1 gate_string_t executable_path = GATE_STRING_INIT_EMPTY;
1378 gate_size_t pos;
1379 1 gate_result_t ret = gate_env_app_executable(&executable_path);
1380
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (GATE_SUCCEEDED(ret))
1381 {
1382 1 pos = gate_string_char_pos_last(&executable_path, '/');
1383
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (GATE_STR_NPOS == pos)
1384 {
1385 ret = GATE_RESULT_INVALIDDATA;
1386 }
1387 else
1388 {
1389
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (NULL == gate_string_substr(apppath, &executable_path, 0, pos + 1))
1390 {
1391 ret = GATE_RESULT_OUTOFMEMORY;
1392 }
1393 else
1394 {
1395 1 ret = GATE_RESULT_OK;
1396 }
1397 1 gate_string_release(&executable_path);
1398 }
1399 }
1400 1 return ret;
1401 }
1402
1403 6 gate_result_t gate_env_data_path(gate_uint32_t dataid, gate_string_t* appdatapath)
1404 {
1405 /*TODO*/
1406 6 gate_result_t ret = GATE_RESULT_NOTSUPPORTED;
1407 switch (dataid)
1408 {
1409 case GATE_ENV_DOCUMENTS:
1410 case GATE_ENV_PICTURES:
1411 case GATE_ENV_MUSIC:
1412 case GATE_ENV_VIDEOS:
1413 case GATE_ENV_DESKTOP:
1414 case GATE_ENV_APPDATA:
1415 default:
1416 {
1417 6 ret = GATE_RESULT_NOTSUPPORTED;
1418 6 break;
1419 }
1420 }
1421 6 return ret;
1422 }
1423
1424 2 gate_result_t gate_env_app_configpath(gate_string_t const* appname, gate_bool_t global_config, gate_string_t* appdatapath)
1425 {
1426 2 gate_result_t ret = GATE_RESULT_OUTOFMEMORY;
1427 gate_strbuilder_t builder;
1428 2 gate_string_t tmp = GATE_STRING_INIT_EMPTY;
1429 2 gate_bool_t appname_empty = gate_string_is_empty(appname);
1430
1431 2 gate_strbuilder_create(&builder, 0);
1432 do
1433 {
1434
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (global_config)
1435 {
1436
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (0 == gate_strbuilder_append_cstr(&builder, "/etc/")) break;
1437 }
1438 else
1439 {
1440 1 ret = gate_env_home_rootpath(&tmp);
1441
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (GATE_FAILED(ret)) break;
1442 1 ret = GATE_RESULT_OUTOFMEMORY;
1443
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (0 == gate_strbuilder_append_string(&builder, &tmp)) break;
1444
1445
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (!appname_empty)
1446 {
1447
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (0 == gate_strbuilder_append_cstr(&builder, ".")) break;
1448 }
1449 }
1450
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (!appname_empty)
1451 {
1452
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (0 == gate_strbuilder_append_string(&builder, appname)) break;
1453
1454 2 mkdir(gate_strbuilder_ptr(&builder, 0), (S_IRUSR | S_IWUSR | S_IXUSR));
1455 }
1456
1457
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 if (NULL != gate_strbuilder_to_string(&builder, appdatapath))
1458 {
1459 2 ret = GATE_RESULT_OK;
1460 }
1461 } while (0);
1462
1463 2 gate_string_release(&tmp);
1464 2 gate_strbuilder_release(&builder);
1465 2 return ret;
1466 }
1467
1468
1469 gate_result_t gate_env_host_name(gate_string_t* hostname)
1470 {
1471 gate_result_t ret = GATE_RESULT_FAILED;
1472 char buffer[GATE_MAX_FILEPATH_LENGTH] = GATE_INIT_EMPTY;
1473 int error = gethostname(buffer, sizeof(buffer));
1474 if (error)
1475 {
1476 gate_posix_errno(&ret);
1477 }
1478 else
1479 {
1480 if (NULL == gate_string_create(hostname, buffer, gate_str_length_max(buffer, sizeof(buffer))))
1481 {
1482 ret = GATE_RESULT_OUTOFMEMORY;
1483 }
1484 else
1485 {
1486 ret = GATE_RESULT_OK;
1487 }
1488 }
1489 return ret;
1490 }
1491 gate_result_t gate_env_user_name(gate_string_t* username)
1492 {
1493 gate_result_t ret = GATE_RESULT_FAILED;
1494 struct passwd* pw = NULL;
1495 uid_t id = geteuid();
1496
1497 do
1498 {
1499 ret = gate_platform_lock();
1500 GATE_BREAK_IF_FAILED(ret);
1501 { /* platform locked */
1502 pw = getpwuid(id);
1503 if (NULL == pw)
1504 {
1505 ret = GATE_RESULT_NOTAVAILABLE;
1506 }
1507 else
1508 {
1509 if (NULL == gate_string_create(username, pw->pw_name, gate_str_length(pw->pw_name)))
1510 {
1511 ret = GATE_RESULT_OUTOFMEMORY;
1512 }
1513 else
1514 {
1515 ret = GATE_RESULT_OK;
1516 }
1517 }
1518 } /* platform unlocked */
1519 gate_platform_unlock();
1520
1521 } while (0);
1522
1523 return ret;
1524 }
1525
1526 1 gate_result_t gate_env_shell_path(gate_string_t* shellpath)
1527 {
1528 static gate_string_t const comspec_var = GATE_STRING_INIT_STATIC("SHELL");
1529 1 gate_result_t result = gate_env_get_var(&comspec_var, shellpath);
1530
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (GATE_FAILED(result))
1531 {
1532 1 gate_string_create_static(shellpath, "/bin/sh");
1533 1 result = GATE_RESULT_OK;
1534 }
1535 1 return result;
1536 }
1537
1538
1539 #endif /* GATE_ENVIRONMENTS_POSIX_IMPL */
1540
1541
1542 #if defined(GATE_ENVIRONMENTS_DOS_IMPL)
1543
1544 gate_result_t gate_env_temp_rootpath(gate_string_t* temppath)
1545 {
1546 gate_result_t ret;
1547 static gate_string_t const tempdir_vars[] =
1548 {
1549 GATE_STRING_INIT_STATIC("TEMP"),
1550 GATE_STRING_INIT_STATIC("TMP")
1551 };
1552 ret = gate_env_select_var(tempdir_vars, sizeof(tempdir_vars) / sizeof(tempdir_vars[0]), temppath);
1553 if (GATE_FAILED(ret))
1554 {
1555 if (NULL != gate_string_create_static(temppath, "C:\\"))
1556 {
1557 ret = GATE_RESULT_OUTOFMEMORY;
1558 }
1559 else
1560 {
1561 ret = GATE_RESULT_OK;
1562 }
1563 }
1564 if (GATE_SUCCEEDED(ret))
1565 {
1566 ret = gate_env_patch_path(temppath);
1567 }
1568 return ret;
1569 }
1570
1571 gate_result_t gate_env_app_executable_name_str(char* buffer, gate_size_t* buffer_len)
1572 {
1573 gate_result_t ret = GATE_RESULT_FAILED;
1574 if (!buffer || !buffer_len)
1575 {
1576 ret = GATE_RESULT_INVALIDARG;
1577 }
1578 else
1579 {
1580 *buffer_len = 1;
1581 buffer[0] = '\0';
1582 ret = GATE_RESULT_OK;
1583 }
1584 return ret;
1585 }
1586
1587 gate_result_t gate_env_data_path(gate_uint32_t dataid, gate_string_t* datapath)
1588 {
1589 GATE_UNUSED_ARG(dataid);
1590 return gate_env_home_rootpath(datapath);
1591 }
1592
1593 gate_result_t gate_env_app_rootpath(gate_string_t* apppath)
1594 {
1595 return gate_env_get_workpath(apppath);
1596 }
1597 gate_result_t gate_env_app_executable_str(char* buffer, gate_size_t* buffer_len)
1598 {
1599 char const* path = gate_dos_get_app_path();
1600 *buffer_len = gate_str_print_text(buffer, *buffer_len, path, gate_str_length(path));
1601 return GATE_RESULT_OK;
1602 }
1603 gate_result_t gate_env_app_executable(gate_string_t* executablepath)
1604 {
1605 char const* path = gate_dos_get_app_path();
1606 if (NULL == gate_string_create(executablepath, path, gate_str_length(path)))
1607 {
1608 return GATE_RESULT_OUTOFMEMORY;
1609 }
1610 else
1611 {
1612 return GATE_RESULT_OK;
1613 }
1614 }
1615
1616 static gate_string_t const default_dos_host_name = GATE_STRING_INIT_STATIC("doshost");
1617
1618 gate_result_t gate_env_host_name(gate_string_t* hostname)
1619 {
1620 gate_string_duplicate(hostname, &default_dos_host_name);
1621 return GATE_RESULT_OK;
1622 }
1623
1624 static gate_string_t const default_dos_user = GATE_STRING_INIT_STATIC("root");
1625
1626 gate_result_t gate_env_user_name(gate_string_t* username)
1627 {
1628 gate_string_duplicate(username, &default_dos_user);
1629 return GATE_RESULT_OK;
1630 }
1631 gate_result_t gate_env_app_configpath(gate_string_t const* appname, gate_bool_t global_config, gate_string_t* appdatapath)
1632 {
1633 gate_result_t ret;
1634 gate_string_t home_path = GATE_STRING_INIT_EMPTY;
1635 GATE_UNUSED_ARG(global_config);
1636 ret = gate_env_home_rootpath(&home_path);
1637 if (GATE_SUCCEEDED(ret))
1638 {
1639 if (NULL == gate_file_build_path_string(appdatapath, &home_path, appname))
1640 {
1641 ret = GATE_RESULT_OUTOFMEMORY;
1642 }
1643 else
1644 {
1645 ret = GATE_RESULT_OK;
1646 }
1647 }
1648 gate_string_release(&home_path);
1649 return ret;
1650 }
1651
1652 gate_result_t gate_env_shell_path(gate_string_t* shellpath)
1653 {
1654 static gate_string_t const comspec_var = GATE_STRING_INIT_STATIC("COMSPEC");
1655 gate_result_t result = gate_env_get_var(&comspec_var, shellpath);
1656 if (GATE_FAILED(result))
1657 {
1658 gate_string_create_static(shellpath, "command.com");
1659 result = GATE_RESULT_OK;
1660 }
1661 return result;
1662 }
1663
1664 #endif /* GATE_ENVIRONMENTS_DOS_IMPL */
1665
1666
1667
1668 #if defined(GATE_ENVIRONMENTS_NO_IMPL)
1669
1670 gate_result_t gate_env_list_vars(gate_env_enum_callback_t callback, void* userparam)
1671 {
1672 /* no env vars, no callback */
1673 GATE_UNUSED_ARG(callback);
1674 GATE_UNUSED_ARG(userparam);
1675 return GATE_RESULT_OK;
1676 }
1677 gate_result_t gate_env_get_var(gate_string_t const* varname, gate_string_t* varvalue)
1678 {
1679 GATE_UNUSED_ARG(varname);
1680 GATE_UNUSED_ARG(varvalue);
1681 return GATE_RESULT_NOMATCH;
1682 }
1683 gate_result_t gate_env_get_var_str(char const* name, gate_size_t name_length, char* value, gate_size_t value_length, gate_size_t* value_used)
1684 {
1685 GATE_UNUSED_ARG(name);
1686 GATE_UNUSED_ARG(name_length);
1687 GATE_UNUSED_ARG(value);
1688 GATE_UNUSED_ARG(value_length);
1689 GATE_UNUSED_ARG(value_used);
1690 return GATE_RESULT_NOMATCH;
1691 }
1692
1693 gate_result_t gate_env_get_workpath(gate_string_t* workpath)
1694 {
1695 GATE_UNUSED_ARG(workpath);
1696 return GATE_RESULT_NOTSUPPORTED;
1697 }
1698 gate_result_t gate_env_set_workpath(gate_string_t const* workpath)
1699 {
1700 GATE_UNUSED_ARG(workpath);
1701 return GATE_RESULT_NOTSUPPORTED;
1702 }
1703
1704 gate_result_t gate_env_temp_rootpath(gate_string_t* temppath)
1705 {
1706 GATE_UNUSED_ARG(temppath);
1707 return GATE_RESULT_NOTSUPPORTED;
1708 }
1709 gate_result_t gate_env_home_rootpath(gate_string_t* homepath)
1710 {
1711 GATE_UNUSED_ARG(homepath);
1712 return GATE_RESULT_NOTSUPPORTED;
1713 }
1714 gate_result_t gate_env_app_rootpath(gate_string_t* apppath)
1715 {
1716 GATE_UNUSED_ARG(apppath);
1717 return GATE_RESULT_NOTSUPPORTED;
1718 }
1719 gate_result_t gate_env_app_executable_str(char* buffer, gate_size_t* buffer_len)
1720 {
1721 GATE_UNUSED_ARG(buffer);
1722 GATE_UNUSED_ARG(buffer_len);
1723 return GATE_RESULT_NOTSUPPORTED;
1724 }
1725 gate_result_t gate_env_app_executable(gate_string_t* executablepath)
1726 {
1727 GATE_UNUSED_ARG(executablepath);
1728 return GATE_RESULT_NOTSUPPORTED;
1729 }
1730 gate_result_t gate_env_app_executable_name_str(char* buffer, gate_size_t* buffer_len)
1731 {
1732 GATE_UNUSED_ARG(buffer);
1733 GATE_UNUSED_ARG(buffer_len);
1734 return GATE_RESULT_NOTSUPPORTED;
1735 }
1736 gate_result_t gate_env_app_configpath(gate_string_t const* appname, gate_bool_t global_config, gate_string_t* appdatapath)
1737 {
1738 GATE_UNUSED_ARG(appname);
1739 GATE_UNUSED_ARG(global_config);
1740 GATE_UNUSED_ARG(appdatapath);
1741 return GATE_RESULT_NOTSUPPORTED;
1742 }
1743
1744 gate_result_t gate_env_data_path(gate_uint32_t dataid, gate_string_t* datapath)
1745 {
1746 GATE_UNUSED_ARG(dataid);
1747 GATE_UNUSED_ARG(datapath);
1748 return GATE_RESULT_NOTSUPPORTED;
1749 }
1750
1751 gate_result_t gate_env_host_name(gate_string_t* hostname)
1752 {
1753 GATE_UNUSED_ARG(hostname);
1754 return GATE_RESULT_NOTSUPPORTED;
1755 }
1756 gate_result_t gate_env_user_name(gate_string_t* username)
1757 {
1758 GATE_UNUSED_ARG(username);
1759 return GATE_RESULT_NOTSUPPORTED;
1760 }
1761
1762 gate_result_t gate_env_shell_path(gate_string_t* shellpath)
1763 {
1764 GATE_UNUSED_ARG(shellpath);
1765 return GATE_RESULT_NOTSUPPORTED;
1766 }
1767
1768
1769 #endif /* GATE_ENVIRONMENTS_NO_IMPL */
1770