GCC Code Coverage Report


Directory: src/gate/
File: src/gate/environments.c
Date: 2025-09-14 13:10:38
Exec Total Coverage
Lines: 141 248 56.9%
Functions: 15 22 68.2%
Branches: 46 122 37.7%

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 1 gate_result_t gate_env_app_executable_name(gate_string_t* executablename)
95 {
96 1 gate_result_t ret = GATE_RESULT_OK;
97 char buffer[GATE_MAX_FILEPATH_LENGTH];
98 1 gate_size_t buffer_len = sizeof(buffer);
99
100 1 ret = gate_env_app_executable_name_str(buffer, &buffer_len);
101
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (GATE_SUCCEEDED(ret))
102 {
103
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (NULL == gate_string_create(executablename, buffer, buffer_len))
104 {
105 ret = GATE_RESULT_OUTOFMEMORY;
106 }
107 }
108 1 return ret;
109 }
110
111 static gate_bool_t gate_env_get_var_map_cb(char const* varname, char const* varvalue, void* userparam)
112 {
113 gate_map_t* ptr_map = (gate_map_t*)userparam;
114 gate_string_t name = GATE_STRING_INIT_EMPTY;
115 gate_string_t value = GATE_STRING_INIT_EMPTY;
116
117 do
118 {
119 if (NULL == gate_string_create(&name, varname, gate_str_length(varname)))
120 {
121 break;
122 }
123 if (NULL == gate_string_create(&value, varvalue, gate_str_length(varvalue)))
124 {
125 break;
126 }
127 gate_map_add(ptr_map, &name, &value);
128 } while (0);
129
130 gate_string_release(&name);
131 gate_string_release(&value);
132 return true;
133 }
134
135 gate_result_t gate_env_get_var_map(gate_map_t* strmap)
136 {
137 gate_result_t ret = GATE_RESULT_FAILED;
138 gate_map_t varmap;
139
140 do
141 {
142 gate_mem_clear(&varmap, sizeof(varmap));
143
144 if (NULL == gate_util_stringmap_create(&varmap))
145 {
146 ret = GATE_RESULT_OUTOFMEMORY;
147 break;
148 }
149
150 ret = gate_env_list_vars(&gate_env_get_var_map_cb, &varmap);
151 GATE_BREAK_IF_FAILED(ret);
152
153 gate_mem_copy(strmap, &varmap, sizeof(varmap));
154 gate_mem_clear(&varmap, sizeof(varmap));
155 ret = GATE_RESULT_OK;
156 } while (0);
157
158 if (GATE_FAILED(ret))
159 {
160 gate_map_destroy(&varmap);
161 }
162
163 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 1 gate_result_t gate_env_list_vars(gate_env_enum_callback_t callback, void* userparam)
904 {
905 gate_result_t ret;
906 1 char const* const* env = (char const* const*)environ;
907 char varname[2048];
908 char varvalue[8192];
909 gate_size_t length;
910 gate_size_t pos;
911
912
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (env == NULL)
913 {
914 ret = GATE_RESULT_NOTAVAILABLE;
915 }
916 else
917 {
918
2/2
✓ Branch 0 taken 88 times.
✓ Branch 1 taken 1 times.
89 while (*env != NULL)
919 {
920 88 length = gate_str_length(*env);
921 88 pos = gate_str_char_pos(*env, length, '=', 0);
922
1/2
✓ Branch 0 taken 88 times.
✗ Branch 1 not taken.
88 if (pos != GATE_STR_NPOS)
923 {
924 88 gate_str_print_text(varname, sizeof(varname), *env, pos);
925 88 gate_str_print_text(varvalue, sizeof(varvalue), &((*env)[pos + 1]), length - pos - 1);
926
1/2
✓ Branch 0 taken 88 times.
✗ Branch 1 not taken.
88 if (callback != NULL)
927 {
928
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 88 times.
88 if (!callback(varname, varvalue, userparam))
929 {
930 break;
931 }
932 }
933 }
934 88 ++env;
935 }
936 1 ret = GATE_RESULT_OK;
937 }
938 1 return ret;
939 }
940 104 gate_result_t gate_env_get_var(gate_string_t const* varname, gate_string_t* varvalue)
941 {
942 gate_result_t ret;
943 char namebuffer[2048];
944 char* ptrenv;
945
946 104 gate_string_to_buffer(varname, namebuffer, sizeof(namebuffer));
947 104 ptrenv = getenv(namebuffer);
948
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 102 times.
104 if (ptrenv == NULL)
949 {
950 2 ret = GATE_RESULT_NOTAVAILABLE;
951 }
952 else
953 {
954
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 102 times.
102 if (NULL == gate_string_create_static_len(varvalue, ptrenv, gate_str_length(ptrenv)))
955 {
956 ret = GATE_RESULT_OUTOFMEMORY;
957 }
958 else
959 {
960 102 ret = GATE_RESULT_OK;
961 }
962 }
963 104 return ret;
964 }
965 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)
966 {
967 gate_result_t ret;
968 char namebuffer[2048];
969 char* ptrenv;
970 gate_size_t used;
971 gate_str_print_text(namebuffer, sizeof(namebuffer), varname, name_length);
972 ptrenv = getenv(namebuffer);
973 if (ptrenv == NULL)
974 {
975 ret = GATE_RESULT_NOTAVAILABLE;
976 }
977 else
978 {
979 used = gate_str_print_text(value, value_length, ptrenv, gate_str_length(ptrenv));
980 if (value_used != NULL)
981 {
982 *value_used = used;
983 }
984 ret = GATE_RESULT_OK;
985 }
986 return ret;
987 }
988
989 5 gate_result_t gate_env_get_workpath(gate_string_t* workpath)
990 {
991 gate_result_t ret;
992 char path[GATE_MAX_FILEPATH_LENGTH];
993 5 gate_size_t length = sizeof(path) - 1;
994 5 char* ptr = getcwd(path, length);
995
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (ptr == NULL)
996 {
997 ret = GATE_RESULT_FAILED;
998 }
999 else
1000 {
1001 5 length = gate_str_length(ptr);
1002
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (path[length - 1] != gate_file_path_separator_char)
1003 {
1004 5 path[length] = gate_file_path_separator_char;
1005 5 ++length;
1006 }
1007
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
5 if (NULL == gate_string_create(workpath, path, length))
1008 {
1009 ret = GATE_RESULT_OUTOFMEMORY;
1010 }
1011 else
1012 {
1013 5 ret = GATE_RESULT_OK;
1014 }
1015 }
1016 5 return ret;
1017 }
1018
1019 1 gate_result_t gate_env_set_workpath(gate_string_t const* workpath)
1020 {
1021 gate_result_t ret;
1022 char path[GATE_MAX_FILEPATH_LENGTH];
1023 1 gate_string_to_buffer(workpath, path, sizeof(path));
1024
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (-1 == chdir(path))
1025 {
1026 ret = gate_platform_print_last_error(NULL, 0);
1027 }
1028 else
1029 {
1030 1 ret = GATE_RESULT_OK;
1031 }
1032 1 return ret;
1033 }
1034
1035 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)
1036 {
1037 gate_size_t cnt;
1038 14 gate_result_t ret = GATE_RESULT_NOTAVAILABLE;
1039
1040
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 for (cnt = 0; cnt != env_vars_count; ++cnt)
1041 {
1042 14 ret = gate_env_get_var(&env_vars[cnt], output);
1043
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 if (GATE_SUCCEEDED(ret))
1044 {
1045 14 return ret;
1046 }
1047 }
1048 return ret;
1049 }
1050
1051 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)
1052 {
1053 gate_result_t ret;
1054 14 ret = gate_env_select_var(ptr_env_names, env_names_count, out_path);
1055
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 if (GATE_SUCCEEDED(ret))
1056 {
1057 14 ret = gate_env_patch_path(out_path);
1058 }
1059 14 return ret;
1060
1061 }
1062
1063 14 gate_result_t gate_env_home_rootpath(gate_string_t* homepath)
1064 {
1065 gate_result_t ret;
1066 static gate_string_t const homedir_vars[] =
1067 {
1068 GATE_STRING_INIT_STATIC("HOME"),
1069 GATE_STRING_INIT_STATIC("USERPROFILE")
1070 };
1071 14 ret = gate_env_read_path_entry(homedir_vars, sizeof(homedir_vars) / sizeof(homedir_vars[0]), homepath);
1072
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (GATE_FAILED(ret))
1073 {
1074 ret = gate_env_temp_rootpath(homepath);
1075 }
1076 14 return ret;
1077 }
1078
1079
1080 #endif /* GATE_ENVIRONMENTS_C_ENV */
1081
1082
1083
1084 #if defined(GATE_ENVIRONMENTS_POSIX_IMPL)
1085
1086 #if defined(GATE_SYS_BSD)
1087 # include <sys/sysctl.h>
1088 # include <sys/stat.h>
1089 # include <unistd.h>
1090
1091 #if defined(KERN_PROC_PATHNAME)
1092
1093 static gate_size_t bsd_get_first_process_arg(char* buffer, gate_size_t buffer_capacity)
1094 {
1095 int mib[4];
1096 char buf[PATH_MAX];
1097 size_t cb = sizeof(buf);
1098
1099 mib[0] = CTL_KERN;
1100 mib[1] = KERN_PROC;
1101 mib[2] = KERN_PROC_PATHNAME;
1102 mib[3] = -1;
1103
1104 gate_mem_clear(buf, sizeof(buf));
1105 if (0 == sysctl(mib, 4, buf, &cb, NULL, 0))
1106 {
1107 return gate_str_print_text(buffer, buffer_capacity, &buf[0], gate_str_length(&buf[0]));
1108 }
1109 return 0;
1110 }
1111
1112 #else /* defined(KERN_PROC_PATHNAME) */
1113
1114 static gate_size_t bsd_get_first_process_arg(char* buffer, gate_size_t buffer_capacity)
1115 {
1116 int mib[4];
1117 char** argv;
1118 size_t len;
1119
1120 mib[0] = CTL_KERN;
1121 mib[1] = KERN_PROC_ARGS;
1122 mib[2] = getpid();
1123 mib[3] = KERN_PROC_ARGV;
1124
1125 if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), NULL, &len, NULL, 0) < 0)
1126 {
1127 return 0;
1128 }
1129 argv = (char**)gate_mem_alloc(len);
1130 if (argv == NULL)
1131 {
1132 return 0;
1133 }
1134
1135 if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), argv, &len, NULL, 0) < 0)
1136 {
1137 len = 0;
1138 }
1139 else
1140 {
1141 len = gate_str_print_text(buffer, buffer_capacity, argv[0], gate_str_length(argv[0]));
1142 }
1143 gate_mem_dealloc(argv);
1144 return len;
1145 }
1146 #endif /* defined(KERN_PROC_PATHNAME) */
1147
1148 static gate_size_t bsd_get_valid_path(char const* base_path, gate_size_t base_path_len,
1149 char const* rel_path, gate_size_t rel_path_len,
1150 char* target_path, gate_size_t target_path_capacity)
1151 {
1152 gate_strbuilder_t builder;
1153 struct stat filestat;
1154 gate_strbuilder_create_static(&builder, target_path, target_path_capacity, 0);
1155 gate_strbuilder_append_text(&builder, base_path, base_path_len);
1156 if (base_path[base_path_len - 1] != '/')
1157 {
1158 gate_strbuilder_append_text(&builder, "/", 1);
1159 }
1160 gate_strbuilder_append_text(&builder, rel_path, rel_path_len);
1161
1162 if (0 == stat(gate_strbuilder_ptr(&builder, 0), &filestat))
1163 {
1164 if (filestat.st_mode & S_IXUSR)
1165 {
1166 return gate_str_print_text(target_path, target_path_capacity, gate_strbuilder_ptr(&builder, 0), gate_strbuilder_length(&builder));
1167 }
1168 }
1169 return 0;
1170 }
1171
1172 gate_size_t bsd_get_process_executable(char* buffer, gate_size_t buffer_capacity)
1173 {
1174 char full_path[PATH_MAX];
1175 gate_size_t full_path_used;
1176 gate_size_t buffer_used;
1177 char const* path_var;
1178 gate_size_t path_len;
1179 gate_size_t start, pos;
1180
1181 buffer_used = bsd_get_first_process_arg(buffer, buffer_capacity);
1182 if (buffer_used == 0)
1183 {
1184 return 0;
1185 }
1186
1187 if ((buffer[0] == '/') || (buffer[0] == '.'))
1188 {
1189 if (NULL == realpath(buffer, full_path))
1190 {
1191 return 0;
1192 }
1193 full_path_used = gate_str_length(full_path);
1194 return gate_str_print_text(buffer, buffer_capacity, full_path, full_path_used);
1195 }
1196
1197 path_var = getenv("PATH");
1198 if (path_var == NULL)
1199 {
1200 return 0;
1201 }
1202 path_len = gate_str_length(path_var);
1203 start = 0;
1204 while (start < path_len)
1205 {
1206 /* abc:def:ghi*/
1207 pos = gate_str_char_pos(path_var, path_len, ':', start);
1208 if (pos == GATE_STR_NPOS)
1209 {
1210 pos = path_len;
1211 }
1212
1213 full_path_used = bsd_get_valid_path(&path_var[start], pos - start, buffer, buffer_used, full_path, sizeof(full_path));
1214 if (full_path_used != 0)
1215 {
1216 return gate_str_print_text(buffer, buffer_capacity, full_path, full_path_used);
1217 }
1218 start = pos + 1;
1219 }
1220 return 0;
1221 }
1222
1223 #endif
1224
1225 #if defined(GATE_SYS_DARWIN)
1226
1227 #include "gate/platform/darwin/darwin_gate.h"
1228
1229 #endif
1230
1231
1232 2 gate_result_t gate_env_temp_rootpath(gate_string_t* temppath)
1233 {
1234 gate_result_t ret;
1235 static gate_string_t const tempdir_var = GATE_STRING_INIT_STATIC("TMPDIR");
1236 static gate_string_t const def_tempdir = GATE_STRING_INIT_STATIC("/tmp/");
1237 2 ret = gate_env_get_var(&tempdir_var, temppath);
1238
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (GATE_FAILED(ret))
1239 {
1240 2 gate_string_duplicate(temppath, &def_tempdir);
1241 2 ret = GATE_RESULT_OK;
1242 }
1243 else
1244 {
1245 ret = gate_env_patch_path(temppath);
1246 }
1247 2 return ret;
1248 }
1249 4 gate_result_t gate_env_app_executable_str(char* destbuffer, gate_size_t* destbuffer_length)
1250 {
1251 char buffer[GATE_MAX_FILEPATH_LENGTH];
1252 4 char const* ptr_path = NULL;
1253 4 gate_size_t destbuffer_used = 0;
1254 ssize_t len_used;
1255
1256 do
1257 {
1258 4 gate_mem_clear(&buffer[0], sizeof(buffer));
1259
1260 #if defined(GATE_SYS_BSD)
1261 destbuffer_used = bsd_get_process_executable(buffer, sizeof(buffer));
1262 if (destbuffer_used != 0)
1263 {
1264 ptr_path = &buffer[0];
1265 break;
1266 }
1267 #endif /* GATE_SYS_BSD */
1268
1269 #if defined(GATE_SYS_DARWIN)
1270 if (GATE_SUCCEEDED(gate_darwin_get_pid_path(gate_darwin_get_pid(), buffer, sizeof(buffer), &destbuffer_used)))
1271 {
1272 ptr_path = &buffer[0];
1273 break;
1274 }
1275 #endif /* GATE_SYS_DARWIN */
1276
1277 /* try procfs fall backs */
1278 4 len_used = readlink("/proc/self/exe", buffer, sizeof(buffer));
1279
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (len_used > 0)
1280 {
1281
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 if (gate_posix_path_exists(&buffer[0]))
1282 {
1283 4 ptr_path = &buffer[0];
1284 4 break;
1285 }
1286 }
1287
1288 len_used = readlink("/proc/curproc/file", buffer, sizeof(buffer));
1289 if (len_used > 0)
1290 {
1291 if (gate_posix_path_exists(&buffer[0]))
1292 {
1293 ptr_path = &buffer[0];
1294 break;
1295 }
1296 }
1297
1298 len_used = readlink("/proc/self/path/a.out", buffer, sizeof(buffer));
1299 if (len_used > 0)
1300 {
1301 if (gate_posix_path_exists(&buffer[0]))
1302 {
1303 ptr_path = &buffer[0];
1304 break;
1305 }
1306 }
1307
1308 #if defined(GATE_SYS_ANDROID)
1309 /* fall-back to procfs required! */
1310 #elif defined(GATE_SYS_LINUX)
1311 ptr_path = (char const*)getauxval(AT_EXECFN);
1312 if (gate_posix_path_exists(ptr_path))
1313 {
1314 break;
1315 }
1316 #endif
1317 /* unfortunately no valid path was found */
1318 ptr_path = NULL;
1319 } while (0);
1320
1321
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ptr_path == NULL)
1322 {
1323 return GATE_RESULT_FAILED;
1324 }
1325 else
1326 {
1327 4 destbuffer_used = gate_str_print_text(destbuffer, *destbuffer_length, ptr_path, gate_str_length(ptr_path));
1328
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (destbuffer_used > 0)
1329 {
1330 4 *destbuffer_length = destbuffer_used;
1331 4 return GATE_RESULT_OK;
1332 }
1333 else
1334 {
1335 return GATE_RESULT_OUTOFMEMORY;
1336 }
1337 }
1338 }
1339
1340 2 gate_result_t gate_env_app_executable(gate_string_t* executablepath)
1341 {
1342 2 char buffer[GATE_MAX_FILEPATH_LENGTH] = GATE_INIT_EMPTY;
1343 2 gate_size_t buffer_len = sizeof(buffer);
1344 2 gate_result_t ret = gate_env_app_executable_str(buffer, &buffer_len);
1345
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (GATE_SUCCEEDED(ret))
1346 {
1347
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (NULL == gate_string_create(executablepath, buffer, buffer_len))
1348 {
1349 ret = GATE_RESULT_OUTOFMEMORY;
1350 }
1351 }
1352 2 return ret;
1353 }
1354
1355 2 gate_result_t gate_env_app_executable_name_str(char* name_buffer, gate_size_t* name_buffer_len)
1356 {
1357 2 char buffer[GATE_MAX_FILEPATH_LENGTH] = GATE_INIT_EMPTY;
1358 2 gate_size_t buffer_len = sizeof(buffer);
1359 2 gate_result_t ret = gate_env_app_executable_str(buffer, &buffer_len);
1360 gate_size_t pos;
1361 gate_size_t name_buffer_used;
1362
1363
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (GATE_SUCCEEDED(ret))
1364 {
1365 2 pos = gate_str_find_last_of(buffer, buffer_len, "/", 1);
1366
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (pos != GATE_STR_NPOS)
1367 {
1368 2 name_buffer_used = gate_str_print_text(name_buffer, *name_buffer_len, &buffer[pos + 1], buffer_len - pos - 1);
1369 }
1370 else
1371 {
1372 name_buffer_used = gate_str_print_text(name_buffer, *name_buffer_len, buffer, buffer_len);
1373 }
1374 2 *name_buffer_len = name_buffer_used;
1375 }
1376 2 return ret;
1377 }
1378
1379
1380 1 gate_result_t gate_env_app_rootpath(gate_string_t* apppath)
1381 {
1382 1 gate_string_t executable_path = GATE_STRING_INIT_EMPTY;
1383 gate_size_t pos;
1384 1 gate_result_t ret = gate_env_app_executable(&executable_path);
1385
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (GATE_SUCCEEDED(ret))
1386 {
1387 1 pos = gate_string_char_pos_last(&executable_path, '/');
1388
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (GATE_STR_NPOS == pos)
1389 {
1390 ret = GATE_RESULT_INVALIDDATA;
1391 }
1392 else
1393 {
1394
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (NULL == gate_string_substr(apppath, &executable_path, 0, pos + 1))
1395 {
1396 ret = GATE_RESULT_OUTOFMEMORY;
1397 }
1398 else
1399 {
1400 1 ret = GATE_RESULT_OK;
1401 }
1402 1 gate_string_release(&executable_path);
1403 }
1404 }
1405 1 return ret;
1406 }
1407
1408 gate_result_t gate_env_data_path(gate_uint32_t dataid, gate_string_t* appdatapath)
1409 {
1410 /*TODO*/
1411 gate_result_t ret = GATE_RESULT_NOTSUPPORTED;
1412 switch (dataid)
1413 {
1414 case GATE_ENV_DOCUMENTS:
1415 case GATE_ENV_PICTURES:
1416 case GATE_ENV_MUSIC:
1417 case GATE_ENV_VIDEOS:
1418 case GATE_ENV_DESKTOP:
1419 case GATE_ENV_APPDATA:
1420 default:
1421 {
1422 ret = GATE_RESULT_NOTSUPPORTED;
1423 break;
1424 }
1425 }
1426 return ret;
1427 }
1428
1429 2 gate_result_t gate_env_app_configpath(gate_string_t const* appname, gate_bool_t global_config, gate_string_t* appdatapath)
1430 {
1431 2 gate_result_t ret = GATE_RESULT_OUTOFMEMORY;
1432 gate_strbuilder_t builder;
1433 2 gate_string_t tmp = GATE_STRING_INIT_EMPTY;
1434 2 gate_bool_t appname_empty = gate_string_is_empty(appname);
1435
1436 2 gate_strbuilder_create(&builder, 0);
1437 do
1438 {
1439
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (global_config)
1440 {
1441
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (0 == gate_strbuilder_append_cstr(&builder, "/etc/")) break;
1442 }
1443 else
1444 {
1445 1 ret = gate_env_home_rootpath(&tmp);
1446
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (GATE_FAILED(ret)) break;
1447 1 ret = GATE_RESULT_OUTOFMEMORY;
1448
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (0 == gate_strbuilder_append_string(&builder, &tmp)) break;
1449
1450
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (!appname_empty)
1451 {
1452
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (0 == gate_strbuilder_append_cstr(&builder, ".")) break;
1453 }
1454 }
1455
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (!appname_empty)
1456 {
1457
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (0 == gate_strbuilder_append_string(&builder, appname)) break;
1458
1459 2 mkdir(gate_strbuilder_ptr(&builder, 0), (S_IRUSR | S_IWUSR | S_IXUSR));
1460 }
1461
1462
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 if (NULL != gate_strbuilder_to_string(&builder, appdatapath))
1463 {
1464 2 ret = GATE_RESULT_OK;
1465 }
1466 } while (0);
1467
1468 2 gate_string_release(&tmp);
1469 2 gate_strbuilder_release(&builder);
1470 2 return ret;
1471 }
1472
1473
1474 gate_result_t gate_env_host_name(gate_string_t* hostname)
1475 {
1476 gate_result_t ret = GATE_RESULT_FAILED;
1477 char buffer[GATE_MAX_FILEPATH_LENGTH] = GATE_INIT_EMPTY;
1478 int error = gethostname(buffer, sizeof(buffer));
1479 if (error)
1480 {
1481 gate_posix_errno(&ret);
1482 }
1483 else
1484 {
1485 if (NULL == gate_string_create(hostname, buffer, gate_str_length_max(buffer, sizeof(buffer))))
1486 {
1487 ret = GATE_RESULT_OUTOFMEMORY;
1488 }
1489 else
1490 {
1491 ret = GATE_RESULT_OK;
1492 }
1493 }
1494 return ret;
1495 }
1496 gate_result_t gate_env_user_name(gate_string_t* username)
1497 {
1498 gate_result_t ret = GATE_RESULT_FAILED;
1499 struct passwd* pw = NULL;
1500 uid_t id = geteuid();
1501
1502 do
1503 {
1504 ret = gate_platform_lock();
1505 GATE_BREAK_IF_FAILED(ret);
1506 { /* platform locked */
1507 pw = getpwuid(id);
1508 if (NULL == pw)
1509 {
1510 ret = GATE_RESULT_NOTAVAILABLE;
1511 }
1512 else
1513 {
1514 if (NULL == gate_string_create(username, pw->pw_name, gate_str_length(pw->pw_name)))
1515 {
1516 ret = GATE_RESULT_OUTOFMEMORY;
1517 }
1518 else
1519 {
1520 ret = GATE_RESULT_OK;
1521 }
1522 }
1523 } /* platform unlocked */
1524 gate_platform_unlock();
1525
1526 } while (0);
1527
1528 return ret;
1529 }
1530
1531 gate_result_t gate_env_shell_path(gate_string_t* shellpath)
1532 {
1533 static gate_string_t const comspec_var = GATE_STRING_INIT_STATIC("SHELL");
1534 gate_result_t result = gate_env_get_var(&comspec_var, shellpath);
1535 if (GATE_FAILED(result))
1536 {
1537 gate_string_create_static(shellpath, "/bin/sh");
1538 result = GATE_RESULT_OK;
1539 }
1540 return result;
1541 }
1542
1543
1544 #endif /* GATE_ENVIRONMENTS_POSIX_IMPL */
1545
1546
1547 #if defined(GATE_ENVIRONMENTS_DOS_IMPL)
1548
1549 gate_result_t gate_env_temp_rootpath(gate_string_t* temppath)
1550 {
1551 gate_result_t ret;
1552 static gate_string_t const tempdir_vars[] =
1553 {
1554 GATE_STRING_INIT_STATIC("TEMP"),
1555 GATE_STRING_INIT_STATIC("TMP")
1556 };
1557 ret = gate_env_select_var(tempdir_vars, sizeof(tempdir_vars) / sizeof(tempdir_vars[0]), temppath);
1558 if (GATE_FAILED(ret))
1559 {
1560 if (NULL != gate_string_create_static(temppath, "C:\\"))
1561 {
1562 ret = GATE_RESULT_OUTOFMEMORY;
1563 }
1564 else
1565 {
1566 ret = GATE_RESULT_OK;
1567 }
1568 }
1569 if (GATE_SUCCEEDED(ret))
1570 {
1571 ret = gate_env_patch_path(temppath);
1572 }
1573 return ret;
1574 }
1575
1576 gate_result_t gate_env_app_executable_name_str(char* buffer, gate_size_t* buffer_len)
1577 {
1578 gate_result_t ret = GATE_RESULT_FAILED;
1579 if (!buffer || !buffer_len)
1580 {
1581 ret = GATE_RESULT_INVALIDARG;
1582 }
1583 else
1584 {
1585 *buffer_len = 1;
1586 buffer[0] = '\0';
1587 ret = GATE_RESULT_OK;
1588 }
1589 return ret;
1590 }
1591
1592 gate_result_t gate_env_data_path(gate_uint32_t dataid, gate_string_t* datapath)
1593 {
1594 GATE_UNUSED_ARG(dataid);
1595 return gate_env_home_rootpath(datapath);
1596 }
1597
1598 gate_result_t gate_env_app_rootpath(gate_string_t* apppath)
1599 {
1600 return gate_env_get_workpath(apppath);
1601 }
1602 gate_result_t gate_env_app_executable_str(char* buffer, gate_size_t* buffer_len)
1603 {
1604 char const* path = gate_dos_get_app_path();
1605 *buffer_len = gate_str_print_text(buffer, *buffer_len, path, gate_str_length(path));
1606 return GATE_RESULT_OK;
1607 }
1608 gate_result_t gate_env_app_executable(gate_string_t* executablepath)
1609 {
1610 char const* path = gate_dos_get_app_path();
1611 if (NULL == gate_string_create(executablepath, path, gate_str_length(path)))
1612 {
1613 return GATE_RESULT_OUTOFMEMORY;
1614 }
1615 else
1616 {
1617 return GATE_RESULT_OK;
1618 }
1619 }
1620
1621 static gate_string_t const default_dos_host_name = GATE_STRING_INIT_STATIC("doshost");
1622
1623 gate_result_t gate_env_host_name(gate_string_t* hostname)
1624 {
1625 gate_string_duplicate(hostname, &default_dos_host_name);
1626 return GATE_RESULT_OK;
1627 }
1628
1629 static gate_string_t const default_dos_user = GATE_STRING_INIT_STATIC("root");
1630
1631 gate_result_t gate_env_user_name(gate_string_t* username)
1632 {
1633 gate_string_duplicate(username, &default_dos_user);
1634 return GATE_RESULT_OK;
1635 }
1636 gate_result_t gate_env_app_configpath(gate_string_t const* appname, gate_bool_t global_config, gate_string_t* appdatapath)
1637 {
1638 gate_result_t ret;
1639 gate_string_t home_path = GATE_STRING_INIT_EMPTY;
1640 GATE_UNUSED_ARG(global_config);
1641 ret = gate_env_home_rootpath(&home_path);
1642 if (GATE_SUCCEEDED(ret))
1643 {
1644 if (NULL == gate_file_build_path_string(appdatapath, &home_path, appname))
1645 {
1646 ret = GATE_RESULT_OUTOFMEMORY;
1647 }
1648 else
1649 {
1650 ret = GATE_RESULT_OK;
1651 }
1652 }
1653 gate_string_release(&home_path);
1654 return ret;
1655 }
1656
1657 gate_result_t gate_env_shell_path(gate_string_t* shellpath)
1658 {
1659 static gate_string_t const comspec_var = GATE_STRING_INIT_STATIC("COMSPEC");
1660 gate_result_t result = gate_env_get_var(&comspec_var, shellpath);
1661 if (GATE_FAILED(result))
1662 {
1663 gate_string_create_static(shellpath, "command.com");
1664 result = GATE_RESULT_OK;
1665 }
1666 return result;
1667 }
1668
1669 #endif /* GATE_ENVIRONMENTS_DOS_IMPL */
1670
1671
1672
1673 #if defined(GATE_ENVIRONMENTS_NO_IMPL)
1674
1675 gate_result_t gate_env_list_vars(gate_env_enum_callback_t callback, void* userparam)
1676 {
1677 /* no env vars, no callback */
1678 GATE_UNUSED_ARG(callback);
1679 GATE_UNUSED_ARG(userparam);
1680 return GATE_RESULT_OK;
1681 }
1682 gate_result_t gate_env_get_var(gate_string_t const* varname, gate_string_t* varvalue)
1683 {
1684 GATE_UNUSED_ARG(varname);
1685 GATE_UNUSED_ARG(varvalue);
1686 return GATE_RESULT_NOMATCH;
1687 }
1688 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)
1689 {
1690 GATE_UNUSED_ARG(name);
1691 GATE_UNUSED_ARG(name_length);
1692 GATE_UNUSED_ARG(value);
1693 GATE_UNUSED_ARG(value_length);
1694 GATE_UNUSED_ARG(value_used);
1695 return GATE_RESULT_NOMATCH;
1696 }
1697
1698 gate_result_t gate_env_get_workpath(gate_string_t* workpath)
1699 {
1700 GATE_UNUSED_ARG(workpath);
1701 return GATE_RESULT_NOTSUPPORTED;
1702 }
1703 gate_result_t gate_env_set_workpath(gate_string_t const* workpath)
1704 {
1705 GATE_UNUSED_ARG(workpath);
1706 return GATE_RESULT_NOTSUPPORTED;
1707 }
1708
1709 gate_result_t gate_env_temp_rootpath(gate_string_t* temppath)
1710 {
1711 GATE_UNUSED_ARG(temppath);
1712 return GATE_RESULT_NOTSUPPORTED;
1713 }
1714 gate_result_t gate_env_home_rootpath(gate_string_t* homepath)
1715 {
1716 GATE_UNUSED_ARG(homepath);
1717 return GATE_RESULT_NOTSUPPORTED;
1718 }
1719 gate_result_t gate_env_app_rootpath(gate_string_t* apppath)
1720 {
1721 GATE_UNUSED_ARG(apppath);
1722 return GATE_RESULT_NOTSUPPORTED;
1723 }
1724 gate_result_t gate_env_app_executable_str(char* buffer, gate_size_t* buffer_len)
1725 {
1726 GATE_UNUSED_ARG(buffer);
1727 GATE_UNUSED_ARG(buffer_len);
1728 return GATE_RESULT_NOTSUPPORTED;
1729 }
1730 gate_result_t gate_env_app_executable(gate_string_t* executablepath)
1731 {
1732 GATE_UNUSED_ARG(executablepath);
1733 return GATE_RESULT_NOTSUPPORTED;
1734 }
1735 gate_result_t gate_env_app_executable_name_str(char* buffer, gate_size_t* buffer_len)
1736 {
1737 GATE_UNUSED_ARG(buffer);
1738 GATE_UNUSED_ARG(buffer_len);
1739 return GATE_RESULT_NOTSUPPORTED;
1740 }
1741 gate_result_t gate_env_app_configpath(gate_string_t const* appname, gate_bool_t global_config, gate_string_t* appdatapath)
1742 {
1743 GATE_UNUSED_ARG(appname);
1744 GATE_UNUSED_ARG(global_config);
1745 GATE_UNUSED_ARG(appdatapath);
1746 return GATE_RESULT_NOTSUPPORTED;
1747 }
1748
1749 gate_result_t gate_env_data_path(gate_uint32_t dataid, gate_string_t* datapath)
1750 {
1751 GATE_UNUSED_ARG(dataid);
1752 GATE_UNUSED_ARG(datapath);
1753 return GATE_RESULT_NOTSUPPORTED;
1754 }
1755
1756 gate_result_t gate_env_host_name(gate_string_t* hostname)
1757 {
1758 GATE_UNUSED_ARG(hostname);
1759 return GATE_RESULT_NOTSUPPORTED;
1760 }
1761 gate_result_t gate_env_user_name(gate_string_t* username)
1762 {
1763 GATE_UNUSED_ARG(username);
1764 return GATE_RESULT_NOTSUPPORTED;
1765 }
1766
1767 gate_result_t gate_env_shell_path(gate_string_t* shellpath)
1768 {
1769 GATE_UNUSED_ARG(shellpath);
1770 return GATE_RESULT_NOTSUPPORTED;
1771 }
1772
1773
1774 #endif /* GATE_ENVIRONMENTS_NO_IMPL */
1775