diff --git a/contrib/sdk/sources/newlib/libc/Makefile b/contrib/sdk/sources/newlib/libc/Makefile index d5937c6dfd..77208b6d4f 100644 --- a/contrib/sdk/sources/newlib/libc/Makefile +++ b/contrib/sdk/sources/newlib/libc/Makefile @@ -182,6 +182,7 @@ STDLIB_SRCS= \ gdtoa-gethex.c \ gdtoa-hexnan.c \ getenv.c \ + envlock.c \ getenv_r.c \ itoa.c \ ldiv.c \ diff --git a/contrib/sdk/sources/newlib/libc/Tupfile.lua b/contrib/sdk/sources/newlib/libc/Tupfile.lua index 09586c85e6..7d0a4d57dc 100644 --- a/contrib/sdk/sources/newlib/libc/Tupfile.lua +++ b/contrib/sdk/sources/newlib/libc/Tupfile.lua @@ -165,6 +165,7 @@ STDLIB_SRCS = { "gdtoa-hexnan.c", "getenv.c", "getenv_r.c", + "envlock.c", "itoa.c", "ldiv.c", "labs.c", diff --git a/contrib/sdk/sources/newlib/libc/crt/crtdll.c b/contrib/sdk/sources/newlib/libc/crt/crtdll.c index 4bc60c3e75..57681a1e3f 100644 --- a/contrib/sdk/sources/newlib/libc/crt/crtdll.c +++ b/contrib/sdk/sources/newlib/libc/crt/crtdll.c @@ -34,6 +34,11 @@ struct app_hdr int (*main)(int argc, char **argv, char **envp); }; +#define ENV_SIZE 16 +/* TODO: Make it dynamic?* */ +static char* __environ[ENV_SIZE] = {0}; +char **environ = &__environ[0]; + extern void _pei386_runtime_relocator (void); extern void init_loader(void *libc_image); extern void init_global_reent(void); @@ -46,13 +51,18 @@ extern void* get_entry_point(void *raw); extern void tls_init(void); -char* __appenv; -int __appenv_size; - - -char * __libc_getenv(const char *name) +void init_environ(void) { - return NULL; + ksys_ufile_t envfile = _ksys_load_file("/sys/settings/system.env"); + if (!envfile.data || !envfile.size) + return; + + char *pch = strtok((char*)envfile.data, " \n\t"); + for (size_t env_pos = 0; pch != NULL && env_pos < ENV_SIZE-1; env_pos++) + { + environ[env_pos] = pch; + pch = strtok(NULL, " \n\t"); + } } static int split_cmdline(char *cmdline, char **argv) @@ -210,7 +220,9 @@ void libc_crt_startup (void *libc_base) } argv[argc] = NULL; - retval = header->main(argc, argv, NULL); + init_environ(); + + retval = header->main(argc, argv, environ); done: if(header->__subsystem__ == 3) __fini_conio(); diff --git a/contrib/sdk/sources/newlib/libc/stdlib/envlock.c b/contrib/sdk/sources/newlib/libc/stdlib/envlock.c new file mode 100644 index 0000000000..8c7e171c3f --- /dev/null +++ b/contrib/sdk/sources/newlib/libc/stdlib/envlock.c @@ -0,0 +1,61 @@ +/* +FUNCTION +<<__env_lock>>, <<__env_unlock>>---lock environ variable + +INDEX + __env_lock +INDEX + __env_unlock + +ANSI_SYNOPSIS + #include + void __env_lock (struct _reent *<[reent]>); + void __env_unlock (struct _reent *<[reent]>); + +TRAD_SYNOPSIS + void __env_lock(<[reent]>) + struct _reent *<[reent]>; + + void __env_unlock(<[reent]>) + struct _reent *<[reent]>; + +DESCRIPTION +The <> family of routines call these functions when they need to +modify the environ variable. The version of these routines supplied in the +library use the lock API defined in sys/lock.h. If multiple threads of +execution can call <>, or if <> can be called reentrantly, +then you need to define your own versions of these functions in order to +safely lock the memory pool during a call. If you do not, the memory pool +may become corrupted. + +A call to <> may call <<__env_lock>> recursively; that is, +the sequence of calls may go <<__env_lock>>, <<__env_lock>>, +<<__env_unlock>>, <<__env_unlock>>. Any implementation of these +routines must be careful to avoid causing a thread to wait for a lock +that it already holds. +*/ + +#include "envlock.h" +#include + +#ifndef __SINGLE_THREAD__ +__LOCK_INIT_RECURSIVE(static, __env_lock_object); +#endif + +void +_EXFUN(__env_lock, + (struct _reent *reent)) +{ +#ifndef __SINGLE_THREAD__ + __lock_acquire_recursive (__env_lock_object); +#endif +} + +void +_EXFUN(__env_unlock, + (struct _reent *reent)) +{ +#ifndef __SINGLE_THREAD__ + __lock_release_recursive (__env_lock_object); +#endif +} diff --git a/contrib/sdk/sources/newlib/libc/stdlib/getenv.c b/contrib/sdk/sources/newlib/libc/stdlib/getenv.c index e7dcb9fdd2..2eb3764755 100644 --- a/contrib/sdk/sources/newlib/libc/stdlib/getenv.c +++ b/contrib/sdk/sources/newlib/libc/stdlib/getenv.c @@ -73,7 +73,7 @@ _DEFUN (_findenv, (name, offset), register _CONST char *name _AND int *offset) { - return NULL; //_findenv_r (_REENT, name, offset); + return _findenv_r (_REENT, name, offset); } /* @@ -86,8 +86,7 @@ _DEFUN (getenv, (name), _CONST char *name) { int offset; - - return NULL; //_findenv_r (_REENT, name, &offset); + return _findenv_r (_REENT, name, &offset); } #endif /* !_REENT_ONLY */ diff --git a/contrib/sdk/sources/newlib/libc/stdlib/getenv_r.c b/contrib/sdk/sources/newlib/libc/stdlib/getenv_r.c index b92e74e04d..cdc12c0a98 100644 --- a/contrib/sdk/sources/newlib/libc/stdlib/getenv_r.c +++ b/contrib/sdk/sources/newlib/libc/stdlib/getenv_r.c @@ -85,6 +85,37 @@ _DEFUN (_findenv_r, (reent_ptr, name, offset), register _CONST char *name _AND int *offset) { + register int len; + register char **p; + _CONST char *c; + + ENV_LOCK; + + /* In some embedded systems, this does not get set. This protects + newlib from dereferencing a bad pointer. */ + if (!*p_environ) + { + ENV_UNLOCK; + return NULL; + } + + c = name; + while (*c && *c != '=') c++; + + /* Identifiers may not contain an '=', so cannot match if does */ + if(*c != '=') + { + len = c - name; + for (p = *p_environ; *p; ++p) + if (!strncmp (*p, name, len)) + if (*(c = *p + len) == '=') + { + *offset = p - *p_environ; + ENV_UNLOCK; + return (char *) (++c); + } + } + ENV_UNLOCK; return NULL; } @@ -100,6 +131,5 @@ _DEFUN (_getenv_r, (reent_ptr, name), { int offset; - return NULL; -// return _findenv_r (reent_ptr, name, &offset); + return _findenv_r (reent_ptr, name, &offset); } diff --git a/data/Tupfile.lua b/data/Tupfile.lua index d4fe63fe4e..0b15ca3bd1 100644 --- a/data/Tupfile.lua +++ b/data/Tupfile.lua @@ -60,6 +60,7 @@ img_files = { {"SETTINGS/NETWORK.INI", "common/settings/network.ini"}, {"SETTINGS/SYSTEM.INI", "common/settings/system.ini"}, {"SETTINGS/TASKBAR.INI", "common/settings/taskbar.ini"}, + {"SETTINGS/SYSTEM.ENV", "common/settings/system.env"}, } -- For russian build, add russian-only files. diff --git a/data/common/settings/system.env b/data/common/settings/system.env new file mode 100644 index 0000000000..9654758df8 --- /dev/null +++ b/data/common/settings/system.env @@ -0,0 +1 @@ +HOME=/tmp0/1