GCC Code Coverage Report


Directory: src/gate/
File: src/gate/environments.c
Date: 2026-03-20 22:56:14
Exec Total Coverage
Lines: 201 247 81.4%
Functions: 22 22 100.0%
Branches: 59 122 48.4%

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